日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

java中push和pop指令的作用_汇编语言PUSH和POP指令(压栈和出栈)

發布時間:2023/12/15 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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指令(压栈和出栈)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。