java中push和pop指令的作用_汇编语言PUSH和POP指令(压栈和出栈)
匯編里把一段內存空間定義為一個棧,棧總是先進后出,棧的最大空間為 64K。由于 "棧" 是由高到低使用的,所以新壓入的數據的位置更低,ESP 中的指針將一直指向這個新位置,所以 ESP 中的地址數據是動態的。
PUSH 指令
PUSH 指令首先減少 ESP 的值,再將源操作數復制到堆棧。操作數是 16 位的,則 ESP 減 2,操作數是 32 位的,則 ESP 減 4。PUSH 指令有 3 種格式:
PUSH reg/mem16
PUSH reg/mem32
PUSH inm32
POP指令
POP 指令首先把 ESP 指向的堆棧元素內容復制到一個 16 位或 32 位目的操作數中,再增加 ESP 的值。如果操作數是 16 位的,ESP 加 2,如果操作數是 32 位的,ESP 加 4:
POP reg/mem16
POP reg/mem32
PUSHFD 和 POPFD 指令
PUSHFD 指令把 32 位 EFLAGS 寄存器內容壓入堆棧,而 POPFD 指令則把棧頂單元內容彈出到 EFLAGS 寄存器:
pushfd
popfd
不能用 MOV 指令把標識寄存器內容復制給一個變量,因此,PUSHFD 可能就是保存標志位的最佳途徑。有些時候保存標志寄存器的副本是非常有用的,這樣之后就可以恢復標志寄存器原來的值。通常會用 PUSHFD 和 POPFD 封閉一段代碼:
pushfd?????????? ;保存標志寄存器
;
;任意語句序列
;
popfd?????????? ;恢復標志寄存器
當用這種方式使用入棧和出棧指令時,必須確保程序的執行路徑不會跳過 POPFD 指令。當程序隨著時間不斷修改時,很難記住所有入棧和出棧指令的位置。因此,精確的文檔就顯得至關重要!
一種不容易出錯的保存和恢復標識寄存器的方法是:將它們壓入堆棧后,立即彈出給一個變量:
.data
saveFlags DWORD ?
.code
pushfd ;標識寄存器內容入棧
pop saveFLags ;復制給一個變量
下述語句從同一個變量中恢復標識寄存器內容:
push saveFlags ;被保存的標識入棧
popfd ;復制給標識寄存器
PUSHAD,PUSHA,POPAD 和 POPA
PUSHAD 指令按照 EAX、ECX、EDX、EBX、ESP(執行 PUSHAD 之前的值)、EBP、ESI 和 EDI 的順序,將所有 32 位通用寄存器壓入堆棧。
POPAD 指令按照相反順序將同樣的寄存器彈出堆棧。與之相似,PUSHA 指令按序(AX、CX、DX、BX、SP、BP、SI 和 DI)將 16 位通用寄存器壓入堆棧。
POPA 指令按照相反順序將同樣的寄存器彈出堆棧。在 16 位模式下,只能使用 PUSHA 和 POPA 指令。
如果編寫的過程會修改 32 位寄存器的值,則在過程開始時使用 PUSHAD 指令,在結束時使用 POPAD 指令,以此保存和恢復寄存器的內容。示例如下列代碼段所示:
MySub PROC
pushad ;保存通用寄存器的內容
.
.
mov eax,...
mov edx,...
mov ecx,...
.
.
popad ;恢復通用寄存器的內容
ret
MySub ENDP
必須要指岀,上述示例有一個重要的例外:過程用一個或多個寄存器來返回結果時,不應使用 PUSHA 和 PUSHAD。假設下述 ReadValue 過程用 EAX 返回一個整數;調用 POPAD 將會覆蓋 EAX 中的返回值:
ReadValue PROC
pushad ;保存通用寄存器的內容
.
.
mov eax rreturn_value
.
.
popad ;覆蓋 EAX !
ret
ReadValue ENDP
示例:字符串反轉
現在查看名為 RevStr 的程序:在一個字符串上循環,將每個字符壓入堆棧,再把這些字符從堆棧中彈出(相反順序),并保存回同一個字符串變量。由于堆棧是 LIFO(后進先出)結構,字符串中的字母順序就發生了翻轉:
;字符串翻轉(Revstr.asm)
.386
.model flat,stdcall
.stack 4096
ExitProcess PROTO,dwExitCode:DWORD
.data
aName BYTE "Abraham Lincoln",0
nameSize = ($-aName)-1
.code
main PROC
;將名字壓入堆棧
mov ecx,nameSize
mov esi,0
L1: movzx eax,aName[esi] ;獲取字符
push eax ;壓入堆棧
inc esi
loop L1
;將名字逆序彈出堆棧
;并存入aName數組
mov ecx,nameSize
mov esi,0
L2: pop eax ;獲取字符
mov aName[esi],al ;存入字符串
inc esi
loop L2
INVOKE ExitProcess,0
main ENDP
END main
總結
以上是生活随笔為你收集整理的java中push和pop指令的作用_汇编语言PUSH和POP指令(压栈和出栈)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 用命令实现Win7远程桌面关机和重启
- 下一篇: Java微信公众平台开发之生成带参二维码