(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