我真的不明白如何堆棧命令或堆棧如何工作。推動和彈出的手臂
說,如果我有
PUSH R3
POP R3
1號線:這是否意味着,R3的內容將被放置到堆棧的頂部?如果R3改變,那麼堆棧的內容會改變嗎?
第2行:在第二行,堆棧頂部的內容是否會從堆棧移入R3或者是R3被壓入堆棧的內容是否被彈出堆棧?
而且什麼呢,當一個寄存器中括號包圍,像這樣
POP {LR}
我真的不明白如何堆棧命令或堆棧如何工作。推動和彈出的手臂
說,如果我有
PUSH R3
POP R3
1號線:這是否意味着,R3的內容將被放置到堆棧的頂部?如果R3改變,那麼堆棧的內容會改變嗎?
第2行:在第二行,堆棧頂部的內容是否會從堆棧移入R3或者是R3被壓入堆棧的內容是否被彈出堆棧?
而且什麼呢,當一個寄存器中括號包圍,像這樣
POP {LR}
所提到的棧操作只對在地址部分使用sp
內存操作快捷鍵彈出/推做。例如。
PUSH {r3}
POP {r3}
是
str r3, [sp, #-4]!
ldr r3, [sp], #4
首先操作說別名 「存儲內容的r3
到[sp - #4]
和4遞減sp
」。最後一個「從[sp]
加載r3
並增加sp
4」。
代替{r3}
可以使用任何其它寄存器或寄存器組(例如{r1,r2,r3,lr}
。在機器代碼的位掩碼指定集,所以你不能影響在寄存器中存儲/加載的順序登記。
堆棧中某個點的塊大小是否始終爲4個字節,或者對於使用32位字的系統,情況恰恰如此? – 2014-11-24 10:45:19
你可以在棧上存儲單個字節; 'sp'只是r13寄存器的別名,可以像內存操作中的其他寄存器一樣使用。但是當輸入一個函數時,大多數高級語言都假設'sp'有一定的對齊。在Linux上,EABI需要例如一個8字節對齊的堆棧指針。一些CPU(例如Cortex M3)在進入中斷處理程序時有一定的魔力可以確保這種約束。 – ensc 2014-11-24 22:27:24
我是否正確地說這個堆棧向下增長? – 2014-11-25 17:52:57
最小的ARMv7例如
最好的學習方法是寫最小的例子,仿真器上運行它們,觀察什麼是與GDB所有寄存器會:
/* Save sp before push. */
mov r0, sp
/* Push. */
mov r1, #1
mov r2, #2
push {r1, r2}
/* Save sp after push. */
mov r1, sp
/* Restore. */
mov r3, #0
mov r4, #0
pop {r3, r4}
cmp r3, #1
bne fail
cmp r4, #2
bne fail
/* Check that stack pointer moved down by 8 bytes
* (2 registers x 4 bytes each). */
sub r0, r1
cmp r0, #8
bne fail
在Ubuntu 16.04上運行示例的樣板:https://github.com/cirosantilli/arm-assembly-cheat/blob/cd46bd4ab163b2ef1a7904c017afb0b980f74c88/push.S
括號在手臂裝配符號中被稱爲「註冊表」。 GNU GAS 2.26.1確實不是接受push
和pop
指令沒有大括號,即使是單寄存器推{}
在push r1
。
還要注意的是:根據ARMv7的調用約定
push
和pop
,編譯器經常使用stp
和ldp
代替
它所與各地登記列表中的括號內所做的是正確組裝;它們是正確語法的一部分。我猜你可能會發現一個assonmbler足夠寬容的接受'推r3'沒有他們,但它肯定是非標準的。 – Notlikethat 2014-11-23 22:39:56