1. 程式人生 > >《組合語言(第三版)》王爽筆記(10)CALL和RET指令

《組合語言(第三版)》王爽筆記(10)CALL和RET指令

第十章 CALL和RET指令

call和ret也是轉移指令,它們都修改IP或同時修改CS和IP。他們經常被共同用來實現子程式設計。

ret指令用棧中資料修改IP,實現近轉移。使用方法:ret retf指令用棧中資料修改CS和IP,實現遠轉移。使用方法:retf CPU執行ret時,操作如下: (IP) = ((ss * 16)+sp) (sp) = (sp)+2 相當於進行 pop ip CPU執行retf時,操作如下: (IP) = ((ss * 16)+sp) (sp) = (sp)+2 (CS) = ((ss * 16)+sp) (sp) = (sp)+2 相當於進行 pop ip pop cs

檢測點10.1

1000h 0

CPU執行call指令: (1)將當前的IP或CS和IP壓入棧中。 (2)轉移。 call指令不能實現短轉移,其他與jmp類似。具體分類如下: call 標號(將當前IP壓棧,轉到標號處執行指令)(對應的機器指令中沒有目的地址,只有相對轉移位移) (sp) = (sp)-2 ((ss*16)+sp) = (IP) (IP) = (IP)+16位位移 16位位移 = 標號處地址- call指令後第一個位元組的地址 (-32768-32767) 相當於進行 push ip jmp near ptr 標號

檢測點10.2

6(執行完call s後,IP先變為6,然後將IP的值壓棧,最後跳轉至s)

call far ptr 標號(對應機器指令中有轉移的目的地址) 段間轉移,執行: (sp) = (sp)-2 ((ss * 16)+sp) = (CS) (sp) = (sp)-2 ((ss * 16)+sp) = (IP) (CS)=(標號所在段的段地址) (IP)=(標號在段中的偏移地址) 相當於進行 push cs push ip jmp far ptr 標號

檢測點10.3

1010H(執行完call far ptr s後,IP先變為8,然後將CS、IP的值分別為1000和8依此壓棧,最後再跳轉至s繼續執行)

call 16位reg(轉移地址在暫存器中) 執行: (sp) = (sp)-2 ((ss * 16)+sp) = (IP) (IP) = (16位reg) 相當於 push ip jmp 16位reg

檢測點10.4

0BH

轉移地址在記憶體中: call word ptr 記憶體單元地址 相當於 push ip jmp word ptr 記憶體單元地址 call dword ptr 記憶體單元地址 相當於 push cs push ip jmp dword ptr 記憶體單元地址

檢測點10.5

(1)3(ds與ss中存放的段地址相同,在執行了call word ptr ds:[0EH]之後,程式會先將下一條指令inc ax的偏移量壓棧,然後從ds:[0EH]讀取兩個記憶體單元作為IP的值,即剛剛壓入的指令inc ax的偏移地址,CS:IP從inc ax繼續執行,故最後ax的值為3。) (2)ax=1,bx=0 (程式的一開始將s的偏移量和cs放入ss:[0]和ss:[2]中,然後呼叫call指令,將CS和IP(nop指令的偏移量)依此壓棧後(sp = 0ch)跳轉到s處繼續執行,ax最終為s的偏移量減去nop指令所在位置的偏移量,為1,bx最終為cs的段地址相減,為0。)

在這裡插入圖片描述 程式返回前,(bx) = 8。從s到ret實現了計算2的N次方,N由cx提供。

子程式:具有某些功能的一段程式,在需要的時候用call轉去執行,在子程式後加入ret,實現執行子程式後轉回call之後的指令繼續執行。 具有子程式的程式框架:

assume cs:code
code segment
main:
	...
	call sub1              ;呼叫子程式sub1
	...
	mov ax,4c00h
	int 21h
sub1:                      ;子程式sub1開始
	...
	ret                    ;子程式返回
code ends 
end main

mul指令 使用乘法指令需要注意: (1)兩個相乘的數:必須同時為16位或8位,如果是16位,一個在ax中,另一個在16位reg中或記憶體字單元中。如果是8位,一個在al中,一個在8位reg或記憶體位元組單元中。 (2)結果:8位乘法的結果放在ax中,16位乘法的結果高位放dx,低位放ax。 指令: mul reg 或 mul 記憶體單元 在這裡插入圖片描述 在這裡插入圖片描述 待解決問題: 1.如何儲存子程式需要的引數和產生的返回值? 使用暫存器是最常用的一種方法。 2.如何傳遞批量資料? 將批量資料放入記憶體,將他們所在記憶體空間的首地址放在暫存器中,傳遞給子程式。對於有批量返回結果的子程式,也可以採用類似方法。 3.子程式與主程式使用暫存器衝突 使用棧。在子程式使用暫存器前將暫存器中的值儲存起來,在子程式返回之前把這些儲存的值恢復。

實驗10

1.show_str.asm

assume cs:code, ss:stack

stack segment
	dw 16 dup (0)
stack ends

data segment
	db 'Welcome to masm!',0
data ends

code segment
start: 
	mov dh,8
	mov dl,3
	mov cl,2
	mov ax,data
	mov ds,ax
	mov si,0
	call show_str

	mov ax,4c00h
	int 21h
show_str:
	push cx
	push bx
	push ax
	push si
	push di
	push es
	;using cx, bx, ax, si, di, es
	mov ax, 0b800h
	mov es,ax
	mov bx,0
	mov di,0
	mov al,160
	mul dh
	add bx,ax
	mov al,2
	mul dl
	add bx,ax ;bx stores address of start character
	mov al,cl ;al stores the color of character
char:
	mov ch,0
	mov cl,ds:[si]
	jcxz zero
	mov ch,al
	mov es:[bx+di],cx
	add di,2
	inc si
	jmp char
zero:
	pop es
	pop di
	pop si
	pop ax
	pop bx
	pop cx
	ret

code ends
end start

2.divdw.asm

assume cs:code,ss:stack

stack segment
	dw 16 dup (0)
stack ends

code segment
start:
	mov ax,stack
	mov ss,ax
	mov sp,32
	mov ax,4240h ;L16
	mov dx,000fh ;H16
	mov cx,0ah
	call divdw
	
	mov ax,4c00h
	int 21h

divdw:
	push bx
	;using bx
	mov bx,ax ;bx stores L
	mov ax,dx ;ax stores H
	mov dx,0
	div cx ;after div, ax holds int(H/N), dx holds rem(H/N)
	push ax ; push int(H/N) temporarily
	mov ax,bx ;ax stores L, dx stores rem(H/N)
	div cx 
	mov cx,dx
	pop dx ; dx stores int(H/N)
	
	pop bx
	ret
	
code ends
end start

3.dtoc.asm

assume cs:code,ss:stack

stack segment
	dw 16 dup (0)
stack ends

data segment
	db 10 dup (0)
data ends

code segment
start:
	mov ax,12666
	mov bx,data
	mov ds,bx
	mov si,0
	call dtoc

	mov dh,8
	mov dl,3
	mov cl,2
	call show_str
	
	mov ax,4c00h
	int 21h
	
dtoc:
	push ax
	push si
	push di
	push dx
	push bx
	push cx
	mov di,0
	mov dx,0
	mov bx,10

devide:
	mov cx,ax
	jcxz stop
	div bx
	inc di
	push dx
	mov dx,0
	jmp devide
stop:
	mov cx,di
string:
	pop bx
	add bx,30h
	mov[si],bl
	inc si	
	loop string

	pop cx
	pop bx
	pop dx
	pop di
	pop si
	pop ax
	ret

show_str:
	push cx
	push bx
	push ax
	push si
	push di
	push es
	;using cx, bx, ax, si, di, es
	mov ax, 0b800h
	mov es, ax
	mov bx, 0
	mov di, 0
	mov al, 160
	mul dh
	add bx, ax
	mov al, 2
	mul dl
	add bx, ax ;bx stores address of start character
	mov al, cl ;al stores the color of character
char:   
	mov ch, 0
	mov cl, ds:[si]
	jcxz zero
	mov ch, al
	mov es:[bx+di], cx
	add di, 2
	inc si
	jmp char
zero:   
	pop es
	pop di
	pop si
	pop ax
	pop bx
	pop cx
	ret

code ends 
end start