(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