call指令和ret指令的用法:call和ret指令(一)
可以利用call和ret來實現子程式的機制,框架為:
標號:指令
ret具有子程式的程式框架如下:
assume cs:code
code segment
main: :
:call sub1::
mov ax,4c00h
int 21h
sub1: :
:call sub2::
retsub2: :::
retcode ends
end main
格式:
mul reg
mul 記憶體單元
機制:(1) 兩個單位元組(8位)的數相乘,乙個預設放在al中,另乙個放在8位reg或記憶體位元組單元中,結果存放在ax暫存器中。
(2) 兩個雙位元組(16位)的數相乘,乙個預設放在ax中,另乙個放在16位reg或記憶體單元中,結果高位預設在dx中存放,低位在ax中放。
程式1:計算100*10
100和10小於255,可以做8位乘法,程式如下。
mov al,100
mov bl,10
mul bl
結果:(ax)=1000(03e8h)
程式2:根據提供的n,計算n的3次方。
問題:(1)將引數n儲存在什麼地方?
(2)計算得到的數值,儲存在什麼地方?
回答:用暫存器來儲存引數和結果是最常使用的方法。可以將引數放到bx中;將結果放到dx和ax中,子程式如下:
cube:mov ax,bx
mul bx
mul bx
ret
問題:
(3)暫存器的數量有限,如果需要傳遞的資料有3個,4個或更多直至n個,該怎麼存放?
回答:在這種時候,我們將批量資料放到記憶體中,然後將它們所在記憶體空間的首位址放在暫存器中,傳遞給需要的子程式。
程式3:將字串中的字母轉化為大寫
capital: and byte ptr [si],11011111b ;將ds:si所指單元中的字母轉化為大寫
inc si ;ds:si指向下乙個單元
loop capital
ret
程式4:將data段中的字串全部轉化為大寫
assume cs:code
data segment
db 'word',0
db 'unix',0
db 'wind',0
db 'good',0
data ends
code segment
start: mov ax,data
mov ds,ax
mov bx,0
mov cx,4
s:mov si,bx
call capital
add bx,5
loop s
mov ax,4c00h
int 21h
capital:mov cl,[si]
mov ch,0
jcxz ok
and byte ptr [si],11011111b
inc si
jmp short capital
ok:ret
code ends
end start
分析:這個程式在思想上完全正確,但是在使用cx時,主程式使用cx記錄迴圈次數,可是子程式中也使用了cx,在執行子程式的時候,cx中儲存的迴圈計數值被改變,使得主程式的迴圈出錯。
解決方法:在子程式的開始將子程式中所有用到的暫存器中的內容都儲存起來,在子程式返回前再恢復。可以使用棧來儲存暫存器中的內容。
改進capital:
capital: push cx
push si
change: mov cl,[si]
mov ch,0
jcxz ok
and byte ptr [si],11011111b
inc si
jmp short change
ok: pop si
pop cx
ret
ret和call的原理
1.ret 指令用棧中的資料,修改ip的內容,從而實現近轉移 cpu執行ret指令時,進行下面兩步操作 1 ip ss 16 sp 使用棧頂元素修改ip實現跳轉 2 sp sp 2 2.retf 用棧中的資料,修改cs和ip的內容,從而實現遠轉移 cpu執行retf指令時,進行下面四步操作 1 ip...
函式呼叫時call指令和ret指令
函式呼叫一般是通過 call 指令和ret指令相互配合使用來實現的,當函式執行到call指令時,call指令會做兩件事 1,將當前的ip壓入棧中 2,跳轉到call指令後被呼叫的函式。當被呼叫函式執行完畢之後,通過 ret指令返回到函式中,ret指令也會做兩件事 1,將之前壓入棧中的ip出棧,2,跳...
組合語言 CALL 和RET指令
call和ret指令都是轉移指令,它們都修改ip,但同時修改cs和ip。ret指令用棧中的資料,修改ip的內容,從而實現近轉移。retf指令用棧中的資料,修改cs和ip的內容,從而實現遠轉移。cpu執行ret指令時,進行下面兩步操作 ip ss 16 sp sp sp 2 cpu執行retf指令時,...