(1)PC是程序计数器,存储将要执行的指令地址
(2)LR是链接寄存器,是ARM处理器中一个有特殊用途的寄存器,当调用函数时,返回地址即PC的值被保存到LR中(mov lr,pc)。
(3)IR是指令寄存器,用来保存当前正在执行的一条指令。当执行一条指令时,先把它从内存取到数据寄存器(DR)中,然后再传送至IR。

 

mov   r1, #0x53000000   //立即数寻址方式
立即数要求以“#”作前缀,对于十六进制的数,还要求在#后面加上0x或者&。0x大家很好理解。

STR是比较重要的指令了,跟它对应的是LDR。ARM指令集是加载/存储型的,也就是说它只处理在寄存器中的数据。那么对于系统存储器的访问就经常用到STR和LDR了。STR是把寄存器上的数据传输到指定地址的存储器上。LDR就是把数据从存储器传输到寄存器上。

ARM有两种跳转方式。
(1) mov pc <跳转地址〉
 这种向程序计数器PC直接写跳转地址,能在4GB连续空间内任意跳转。
(2)通过 B BL BLX BX 可以完成在当前指令向前或者向后32MB的地址空间的跳转(为什么是32MB呢?寄存器是32位的,此时的值是24位有符号数,所以32MB)。
B是最简单的跳转指令。要注意的是,跳转指令的实际值不是绝对地址,而是相对地址——是相对当前PC值的一个偏移量,它的值由汇编器计算得出。
BL非常常用。它在跳转之前会在寄存器LR中保存PC的当前内容。BL的经典用法如下:
       bl NEXT   ; 跳转到NEXT
       ……
    NEXT
       ……
       mov pc, lr    ; 从子程序返回。

 

在ARM架构下,  数据从内存到CPU之间的移动只能通过LDR/STR指令来完成.  而MOV只能在寄存器之间移动数据,或者把立即数移动到寄存器中

csel w0, w2, w0, gt
csel根据后面的条件决定如何赋值,如果是GT,则w0=w2,否则w0 = w0。
LDR  R0, [R1] 
这条指令的意思是,将R1中的值作为地址,将地址里面存的值复制给寄存器R0
STR R1,[R0]
这条指令的意思是,将R1里面的值,复制到以R0里面的值作为地址的内存里面。
typedef struct Person {
   int id;
   int age;
   char name[10];
   int sex;
} CPerson;



int getId(CPerson person) {
    return person.id;
}

int getAge(CPerson person) {
    return person.age;
}

int getSex(CPerson person) {
    return person.sex;
}

int run(CPerson person, int age) {
   if (age<7) {
       return 0xffff;
   } else if (age < 13) {
       return age +1;
   } else {
       age = getAge(person);
       return age;
   }
}

int run_1(int x) {
    if (x >15) {
        return 0xffff;
    } else {
        return 0x111;
    }
}

void test() {
    CPerson person ={12, 10, "cm", 1};
    run(person, 10);
}
mutian@mutian:~/share/test/test$ cp ~/workspace/NDK/libs/arm64-v8a/libhello-jni.so .
mutian@mutian:~/share/test/test$ ~/soft/android-ndk-r10e/toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64/bin/aarch64-linux-android-objdump -S -D libhello-jni.so   > x.log
000000000000063c <getId>:
 63c:   b9400000        ldr     w0, [x0]
 640:   d65f03c0        ret

0000000000000644 <getAge>:
 644:   b9400400        ldr     w0, [x0,#4]
 648:   d65f03c0        ret

000000000000064c <getSex>:
 // 这个方法是全局方法,所以x0是第一个参数
 // 结构体按最大的数据类型进行字节对齐,所以sex偏移值是20,而不是18
 // 返回值存放在w0中, w0是x0的低32位
 64c:   b9401400        ldr     w0, [x0,#20]
 650:   d65f03c0        ret

0000000000000654 <run>:
 // stack 扩大30 每个方法调用前就已经知道,这个方法需要多大stack
 654:   d100c3ff        sub     sp, sp, #0x30
 //cmp指令 w1 - 0x6 结果不存储 只更改状态寄存器CPSR中的条件标志位
 658:   7100183f        cmp     w1, #0x6
 65c:   aa0003e2        mov     x2, x0
 660:   529fffe0        mov     w0, #0xffff                     // #65535
 664:   f90003fe        str     x30, [sp]
 668:   5400008c        b.gt    678 <run+0x24>
 66c:   f94003fe        ldr     x30, [sp]
 670:   9100c3ff        add     sp, sp, #0x30
 674:   d65f03c0        ret
 678:   7100303f        cmp     w1, #0xc
 67c:   11000420        add     w0, w1, #0x1
 680:   54ffff6d        b.le    66c <run+0x18>
 684:   a9401444        ldp     x4, x5, [x2]
 688:   f9400841        ldr     x1, [x2,#16]
 68c:   910043e0        add     x0, sp, #0x10
 690:   f90013e1        str     x1, [sp,#32]
 694:   a90117e4        stp     x4, x5, [sp,#16]
 698:   97ffffeb        bl      644 <getAge>
 69c:   f94003fe        ldr     x30, [sp]
 6a0:   9100c3ff        add     sp, sp, #0x30
 6a4:   d65f03c0        ret

00000000000006a8 <run_1>:
 6a8:   71003c1f        cmp     w0, #0xf
 6ac:   529fffe1        mov     w1, #0xffff                     // #65535
 6b0:   52802220        mov     w0, #0x111                      // #273
 6b4:   1a80c020        csel    w0, w1, w0, gt
 6b8:   d65f03c0        ret