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

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

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

發(fā)布時(shí)間:2023/12/15 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java中push和pop指令的作用_汇编语言PUSH和POP指令(压栈和出栈) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

匯編里把一段內(nèi)存空間定義為一個(gè)棧,棧總是先進(jìn)后出,棧的最大空間為 64K。由于 "棧" 是由高到低使用的,所以新壓入的數(shù)據(jù)的位置更低,ESP 中的指針將一直指向這個(gè)新位置,所以 ESP 中的地址數(shù)據(jù)是動(dòng)態(tài)的。

PUSH 指令

PUSH 指令首先減少 ESP 的值,再將源操作數(shù)復(fù)制到堆棧。操作數(shù)是 16 位的,則 ESP 減 2,操作數(shù)是 32 位的,則 ESP 減 4。PUSH 指令有 3 種格式:

PUSH reg/mem16

PUSH reg/mem32

PUSH inm32

POP指令

POP 指令首先把 ESP 指向的堆棧元素內(nèi)容復(fù)制到一個(gè) 16 位或 32 位目的操作數(shù)中,再增加 ESP 的值。如果操作數(shù)是 16 位的,ESP 加 2,如果操作數(shù)是 32 位的,ESP 加 4:

POP reg/mem16

POP reg/mem32

PUSHFD 和 POPFD 指令

PUSHFD 指令把 32 位 EFLAGS 寄存器內(nèi)容壓入堆棧,而 POPFD 指令則把棧頂單元內(nèi)容彈出到 EFLAGS 寄存器:

pushfd

popfd

不能用 MOV 指令把標(biāo)識(shí)寄存器內(nèi)容復(fù)制給一個(gè)變量,因此,PUSHFD 可能就是保存標(biāo)志位的最佳途徑。有些時(shí)候保存標(biāo)志寄存器的副本是非常有用的,這樣之后就可以恢復(fù)標(biāo)志寄存器原來(lái)的值。通常會(huì)用 PUSHFD 和 POPFD 封閉一段代碼:

pushfd?????????? ;保存標(biāo)志寄存器

;

;任意語(yǔ)句序列

;

popfd?????????? ;恢復(fù)標(biāo)志寄存器

當(dāng)用這種方式使用入棧和出棧指令時(shí),必須確保程序的執(zhí)行路徑不會(huì)跳過(guò) POPFD 指令。當(dāng)程序隨著時(shí)間不斷修改時(shí),很難記住所有入棧和出棧指令的位置。因此,精確的文檔就顯得至關(guān)重要!

一種不容易出錯(cuò)的保存和恢復(fù)標(biāo)識(shí)寄存器的方法是:將它們壓入堆棧后,立即彈出給一個(gè)變量:

.data

saveFlags DWORD ?

.code

pushfd ;標(biāo)識(shí)寄存器內(nèi)容入棧

pop saveFLags ;復(fù)制給一個(gè)變量

下述語(yǔ)句從同一個(gè)變量中恢復(fù)標(biāo)識(shí)寄存器內(nèi)容:

push saveFlags ;被保存的標(biāo)識(shí)入棧

popfd ;復(fù)制給標(biāo)識(shí)寄存器

PUSHAD,PUSHA,POPAD 和 POPA

PUSHAD 指令按照 EAX、ECX、EDX、EBX、ESP(執(zhí)行 PUSHAD 之前的值)、EBP、ESI 和 EDI 的順序,將所有 32 位通用寄存器壓入堆棧。

POPAD 指令按照相反順序?qū)⑼瑯拥募拇嫫鲝棾龆褩!Ec之相似,PUSHA 指令按序(AX、CX、DX、BX、SP、BP、SI 和 DI)將 16 位通用寄存器壓入堆棧。

POPA 指令按照相反順序?qū)⑼瑯拥募拇嫫鲝棾龆褩!T?16 位模式下,只能使用 PUSHA 和 POPA 指令。

如果編寫(xiě)的過(guò)程會(huì)修改 32 位寄存器的值,則在過(guò)程開(kāi)始時(shí)使用 PUSHAD 指令,在結(jié)束時(shí)使用 POPAD 指令,以此保存和恢復(fù)寄存器的內(nèi)容。示例如下列代碼段所示:

MySub PROC

pushad ;保存通用寄存器的內(nèi)容

.

.

mov eax,...

mov edx,...

mov ecx,...

.

.

popad ;恢復(fù)通用寄存器的內(nèi)容

ret

MySub ENDP

必須要指岀,上述示例有一個(gè)重要的例外:過(guò)程用一個(gè)或多個(gè)寄存器來(lái)返回結(jié)果時(shí),不應(yīng)使用 PUSHA 和 PUSHAD。假設(shè)下述 ReadValue 過(guò)程用 EAX 返回一個(gè)整數(shù);調(diào)用 POPAD 將會(huì)覆蓋 EAX 中的返回值:

ReadValue PROC

pushad ;保存通用寄存器的內(nèi)容

.

.

mov eax rreturn_value

.

.

popad ;覆蓋 EAX !

ret

ReadValue ENDP

示例:字符串反轉(zhuǎn)

現(xiàn)在查看名為 RevStr 的程序:在一個(gè)字符串上循環(huán),將每個(gè)字符壓入堆棧,再把這些字符從堆棧中彈出(相反順序),并保存回同一個(gè)字符串變量。由于堆棧是 LIFO(后進(jìn)先出)結(jié)構(gòu),字符串中的字母順序就發(fā)生了翻轉(zhuǎn):

;字符串翻轉(zhuǎn)(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數(shù)組

mov ecx,nameSize

mov esi,0

L2: pop eax ;獲取字符

mov aName[esi],al ;存入字符串

inc esi

loop L2

INVOKE ExitProcess,0

main ENDP

END main

總結(jié)

以上是生活随笔為你收集整理的java中push和pop指令的作用_汇编语言PUSH和POP指令(压栈和出栈)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。