2014-11-23 52 views
4

我真的不明白如何堆棧命令或堆棧如何工作。推動和彈出的手臂

說,如果我有

PUSH R3 
POP R3 

1號線:這是否意味着,R3的內容將被放置到堆棧的頂部?如果R3改變,那麼堆棧的內容會改變嗎?

第2行:在第二行,堆棧頂部的內容是否會從堆棧移入R3或者是R3被壓入堆棧的內容是否被彈出堆棧?

而且什麼呢,當一個寄存器中括號包圍,像這樣

POP {LR} 
+2

它所與各地登記列表中的括號內所做的是正確組裝;它們是正確語法的一部分。我猜你可能會發現一個assonmbler足夠寬容的接受'推r3'沒有他們,但它肯定是非標準的。 – Notlikethat 2014-11-23 22:39:56

回答

6

所提到的棧操作只對在地址部分使用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}。在機器代碼的位掩碼指定集,所以你不能影響在寄存器中存儲/加載的順序登記。

+0

堆棧中某個點的塊大小是否始終爲4個字節,或者對於使用32位字的系統,情況恰恰如此? – 2014-11-24 10:45:19

+0

你可以在棧上存儲單個字節; 'sp'只是r13寄​​存器的別名,可以像內存操作中的其他寄存器一樣使用。但是當輸入一個函數時,大多數高級語言都假設'sp'有一定的對齊。在Linux上,EABI需要例如一個8字節對齊的堆棧指針。一些CPU(例如Cortex M3)在進入中斷處理程序時有一定的魔力可以確保這種約束。 – ensc 2014-11-24 22:27:24

+1

我是否正確地說這個堆棧向下增長? – 2014-11-25 17:52:57

2

最小的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確實不是接受pushpop指令沒有大括號,即使是單寄存器推{}push r1

還要注意的是:根據ARMv7的調用約定