8086匯編之 CALL 和 RET指令


Ret 和 call 也是轉移指令,可是他們跟jmp不同的是,這兩個轉移指令都跟棧有關系。

<1> ret

用棧中的數據改動IP的地址,從而實現近轉移

( ip ) = ( (ss)*16+ sp )

( sp ) =( sp ) + 2

相當於pop ip

<2>retf

用棧中的數據來改動CS以及IP的值,實現段間轉移

( ip ) = ( (ss)*16+ sp )

( sp ) =( sp ) + 2

( cs ) = ( (ss)*16+ sp )

( sp ) =( sp ) + 2

相當於

Pop ip

Pop cs

<3> call xxx(行號)

先把當前IP壓棧,然后跳轉,相當於實現近轉移

( sp ) = ( sp ) – 2

( (ss)*16+ sp ) = ( ip )

( ip ) = ( ip ) + 16位位移

相當於:

Push ip

Jmp near ptr xxx(行號)

 

<4>call far ptr

把CS。IP壓棧處理,然后實現跳轉,相當於段間轉移。遠轉移

( sp ) = ( sp ) – 2

( (ss)*16+ sp ) = ( cs )

( sp ) = ( sp ) – 2

( (ss)*16+ sp ) = ( ip )

 

(cs) = 當前行號段地址

(ip) = 當前行號偏移地址

相當於:

Push cs

Push ip

Jmp far ptr xxx

 

<5> call reg(16bit)

跳轉到16位寄存器上中存儲的地址

( sp ) = (sp) – 2

( (SS)*16 + (sp) ) = (IP)

(IP) = ( 16bit Reg )

相當於:

Push IP

Jmp 16bit Reg

<6> call word ptr 內存單元地址

相當於

Push IP

Jmp word ptr 內存單元地址

如:call word ptr ds:[0]

 

<7> call dword ptr 內存單元地址

相當於

Push cs

Push ip

Jmp dword ptr 內存單元地址

比如:jmp dword ptr DS:[0];

<8>寄存器的沖突問題

主程序調用子程序段的時候,可能子程序會用到主程序中使用的寄存器的值。程序在設計的時候不可能做到不讓子程序使用主程序的寄存器,由於兩者是相互獨立的。你永遠不會還有一個會做什么。所以在子程序中採取不使用主程序中調用的寄存器的做法是不可行的。

解決方法:

把寄存器用到的東西,保存到堆棧里面。子程序調用完成。再將堆棧保存的東西彈出。

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM