.data
array_buff:
.word 0x00000000 /* array_buff[0] */
.word 0x00000000 /* array_buff[1] */
.word 0x00000000 /* array_buff[2]. This element has a relative address of array_buff+8 */
.word 0x00000000 /* array_buff[3] */
.word 0x00000000 /* array_buff[4] */
.text
.global _start
_start:
adr r0, words+12 /* address of words[3] -> r0 */
ldr r1, array_buff_bridge /* address of array_buff[0] -> r1 */
ldr r2, array_buff_bridge+4 /* address of array_buff[2] -> r2 */
ldm r0, {r4,r5} /* words[3] -> r4 = 0x03; words[4] -> r5 = 0x04 */
stm r1, {r4,r5} /* r4 -> array_buff[0] = 0x03; r5 -> array_buff[1] = 0x04 */
ldmia r0, {r4-r6} /* words[3] -> r4 = 0x03, words[4] -> r5 = 0x04; words[5] -> r6 = 0x05; */
stmia r1, {r4-r6} /* r4 -> array_buff[0] = 0x03; r5 -> array_buff[1] = 0x04; r6 -> array_buff[2] = 0x05 */
ldmib r0, {r4-r6} /* words[4] -> r4 = 0x04; words[5] -> r5 = 0x05; words[6] -> r6 = 0x06 */
stmib r1, {r4-r6} /* r4 -> array_buff[1] = 0x04; r5 -> array_buff[2] = 0x05; r6 -> array_buff[3] = 0x06 */
ldmda r0, {r4-r6} /* words[3] -> r6 = 0x03; words[2] -> r5 = 0x02; words[1] -> r4 = 0x01 */
ldmdb r0, {r4-r6} /* words[2] -> r6 = 0x02; words[1] -> r5 = 0x01; words[0] -> r4 = 0x00 */
stmda r2, {r4-r6} /* r6 -> array_buff[2] = 0x02; r5 -> array_buff[1] = 0x01; r4 -> array_buff[0] = 0x00 */
stmdb r2, {r4-r5} /* r5 -> array_buff[1] = 0x01; r4 -> array_buff[0] = 0x00; */
bx lr
words:
.word 0x00000000 /* words[0] */
.word 0x00000001 /* words[1] */
.word 0x00000002 /* words[2] */
.word 0x00000003 /* words[3] */
.word 0x00000004 /* words[4] */
.word 0x00000005 /* words[5] */
.word 0x00000006 /* words[6] */
array_buff_bridge:
.word array_buff /* address of array_buff, or in other words - array_buff[0] */
.word array_buff+8 /* address of array_buff[2] */
開始調(diào)試上面的代碼gdb ldr
下斷點(diǎn)
break _start
運(yùn)行
run //運(yùn)行到斷點(diǎn)處
x/i $pc
:查看接下來反匯編指令(60是10進(jìn)制數(shù)衰齐,轉(zhuǎn)成16進(jìn)制為3c)
0x10074 <_start>: add r0, pc, #60 ; 0x3c
使用i r pc
查詢到 的pc當(dāng)前存儲的值為0x10074
pc 0x10074 0x10074 <_start>
也就是說下一條指令是用0x100b0
=(0x10074+0x3c),賦值給r0把敢,但是實(shí)際并不是预茄,執(zhí)行下面的單步執(zhí)行
已卸,執(zhí)行完第一條指令,使用i r r0
發(fā)現(xiàn)結(jié)果為0x100b8
r0 0x100b8 65720
為什么結(jié)果會比計(jì)算的值多8呢?
參考:什么時(shí)候PC+8,PC+4,PC-4,PC-8
[圖片上傳失敗...(image-cefda3-1543372618746)]
需要知道的點(diǎn):
1惑折、每條指令執(zhí)行有三個(gè)流程:取指、譯碼枯跑、執(zhí)行
2惨驶、當(dāng)?shù)谝粭l匯編指令取指完成后,緊接著就是第二條指令的取指敛助,然后第三條...如此嵌套
3粗卜、取指
完成后,PC就指向了第二條指令辜腺,此時(shí)PC=PC+4
所以可以知道:第一條指令執(zhí)行的時(shí)候休建,也是第三條指令的取指的時(shí)候,即PC=PC+8
單步執(zhí)行
nexti/ni //步入
stepi/si //步過
adr r0, words+12
:將words+12處的內(nèi)存地址獲取并存到r0评疗。
words+12->0x00000003(這個(gè)地址存儲的值)测砂,
i r r0 //獲取r0寄存器數(shù)據(jù):0x100b8
x/3w 0x100b8 //十六進(jìn)制,字類型查看0x100b8和其之后的兩個(gè)地址的數(shù)據(jù)
結(jié)果:0x100b8 <words+12>: 3 4 5
ldm r0, {r4, r5}
ldm 源百匆,目的寄存器
:r0的值為內(nèi)存地址砌些,其指向的值附給r4,r0+4指向的值給r5
r0: 寄存其中的值
r0 0x100b8 0x100b8
內(nèi)存地址指向的值
x/w 0x100b8 >> 3
x/w 0x100bc >> 4
stm r1, {r4, r5}
stm 目的地址加匈,{源寄存器}
:將寄存器中的值存璃,放入目的地址指向的位置處
執(zhí)行前:
$r1 : 0x000200d0
$r4 : 0x3
$r5 : 0x4
x/2w 0x100d0 (0x000100d0指向的值>>0x0; 0x000100d4>>0x0)
執(zhí)行后si
:
x/2w 0x200d0
結(jié)果為:0x200d0: 0x3 0x4
ldmia、stmia
-IA(之后遞增)
:ldm 和 ldmia是相同的雕拼,每次加載下一條指令纵东,源地址都會增加4字節(jié)(一個(gè)字的值)
,stmia也一樣
ldmia r0, {r4-r6} /* r0 -> r4 = 0x03, r0+4 -> r5 = 0x04; r0+8 -> r6 = 0x05; */
stmia r1, {r4-r6} /* r4 -> r1 = 0x03; r5 -> r1+4 = 0x04; r6 -> r1+8 = 0x05 */
ldmib啥寇、stmib
-IB(之前遞增)
:在加載下一條指令之前增加4字節(jié)(一個(gè)字的值)
ldmia r0, {r4-r6} /* r0 -> r0+4 = 0x03, r0+8 -> r5 = 0x04; r0+12 -> r6 = 0x05; */
stmia r1, {r4-r6} /* r4 -> r1+4 = 0x03; r5 -> r1+8 = 0x04; r6 -> r1+12 = 0x05 */
LDMDA偎球、STMDA:遞減情況下,目的寄存器是先賦值給后面辑甜,同樣從源寄存器中取指時(shí)也是先從后面取值
-DA(之后遞減)
ldmda r0, {r4-r6} /* r0 -> r6 = 0x03; r0-4 -> r5 = 0x02; r0-8 -> r4 = 0x01 */
stmda r2, {r4-r6} /* r6 -> array_buff[2] = 0x02; r5 -> array_buff[1] = 0x01; r4 -> array_buff[0] = 0x00 */
LDMDB衰絮、STMDB
-DB(之前遞減)
ldmdb r0, {r4-r6} /* r0-4 -> r6 = 0x02; r0-8 -> r5 = 0x01; r0-12 -> r4 = 0x00 */
stmdb r2, {r4-r5} /* r5 -> r2-4 = 0x01; r4 -> r2-8 = 0x00; */
PUSH AND POP
知識點(diǎn)
PUSH
:
- SP-4
- 數(shù)據(jù)存儲到SP指向的新地址處
POP
:
- SP的值先存儲到某個(gè)寄存器中
- SP+4
實(shí)例
.text
.global _start
_start:
mov r0, #3
mov r1, #4
push {r0, r1}
pop {r2, r3}
stmdb sp!, {r0, r1}
ldmia sp!, {r4, r5}
bkpt
匯編后:
0x10054 <_start+0> mov r0, #3
0x10058 <_start+4> mov r1, #4
-> 0x1005c <_start+8> push {r0, r1}
0x10060 <_start+12> pop {r2, r3}
0x10064 <_start+16> push {r0, r1}
0x10068 <_start+20> pop {r4, r5}
0x1006c <_start+24> bkpt 0x0000
- push:先從后面壓入堆棧
0x1005c <_start+8> push {r0, r1} //r0=3;r1=4
堆棧信息:
0xbefff2a8|+0x0000: 0x00000003 <-$sp
0xbefff2ac|+0x0004: 0x00000004
- pop:先賦值給前面的寄存器
0x10060 <_start+12> pop {r2, r3}
寄存器信息
$r2 : 0x3
$r3 : 0x4
-
stmdb sp!
就是push
-
ldmia sp!
就是pop