王爽 《汇编语言》 读书笔记 十 CALL和RET指令

本文详细介绍了汇编语言中的CALL和RET指令,包括它们在子程序设计中的作用,如ret用于近转移,retf用于远转移。讲解了不同类型的CALL指令,如根据位移、内存地址、寄存器进行转移,并讨论了它们与RET的配合使用,以及在模块化程序设计中的参数和结果传递策略。此外,还提到了寄存器冲突问题的解决和数值显示的子程序设计。
摘要由CSDN通过智能技术生成

第十章 CALL和RET指令


call和ret都是转移指令,它们都修改IP,或同时修改CS和IP,常用于子程序的设计。


10.1 ret 和 retf

ret用栈中的数据,修改IP的内容,从而实现近转移

retf指令用栈中的数据,修改CS和IP的内容,从而实现远转移


ret指令

1) (IP) = ((ss)*16 + (sp))

2) (sp) = (sp) + 2

相当于cpu执行来pop IP

retf指令

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

2) (sp) = (sp) + 2

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

4) (sp) = (sp) + 2

相当于cpu执行来pop IP ,  pop CS

以下代码执行以后将跳转到代码段第一条指令

assume cs:code
stack segment
	db 16 dup (0)
stack ends

code segment
		mov ax, 4c00h
		int 21h
		
start:	mov ax, stack
		mov ss, ax
		mov sp, 10h
		mov ax, 0
		push ax
		mov bx, 0
		ret
code ends

end start


监测点10.1

将代码跳转至1000:0000H处

assume cs:code
stack segment
	db 16 dup (0)
stack ends

code segment		
start:	mov ax, stack
		mov ss, ax
		mov sp, 10h
		mov ax, 1000h
		push ax
		mov ax, 0
		push ax
		retf		; equal pop ip, pop cs
code ends

end start


10.2 call指令

call执行

1)将当前的IP或cs和IP压入栈

2)转移

call不能实现短转移,转移方法和jmp指令的原理相同。


10.3  根据位移进行转移的call指令

call 标号(将当前的IP压栈后,转移到标号处执行指令

1) (sp) = (sp) - 2

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

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

16位位移=标号处的地址-call指令后的第一个字节的地址;

16位位移的范围为-32768~32767,用补码表示

16位位移由编译时算出


push IP

jmp near ptr 标号


10.4 转移的目的地址在指令中的call指令

call far ptr 标号  实现段间转移

1) (sp) = (sp) -2 

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

      (sp) = (sp) - 2

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

2)  (cs) = 标号所在的段地址

    (IP) = 标号所在的偏移地址

相当于

push cs

push ip

jmp far ptr 标号


10.5 转移地址在寄存器中的call指令

call 16位 reg

(sp) = (sp) - 2

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

(ip) = (16位reg)


push IP

jum 16位reg


10.6 转移地址在内存中的call指令

两种格式

1) call word ptr 内存单元地址

push IP

jmp word ptr 内存单元地址


2) call dword ptr 内存单元地址

push CS

push IP

jmp dword ptr 内存单元地址


监测点10.5

1)

assume cs:code
stack segment
	dw 8 dup (0)
stack ends

code segment		
start:	mov ax, stack
		mov ss, ax
		mov sp, 10h
		mov ds, ax
		mov ax, 0
		call word ptr ds:[0eh]
		inc ax
		inc ax
		inc ax
		mov ax, 4c00h
		int 21h
code ends

end start
该代码执行到  call word ptr ds:[0eh]

的时候

首先  

a. 执行push ip   (此时的ip是指向下一条inc ax的地址这里称为A)  sp = 10h -2  = 0eh   ((ss)*16 + (sp)) = A

b. jmp word ptr ds:[0eh]     这里的[0eh]就是ss:sp指向的地址A  因此直接跳转至A处执行call语句后面的inc ax

然后inc 3次 ax

最后ax = 3

使用debug单步调试的时候debug程序也会使用相同的stack因此会产生奇怪的问题。


2)ax = 1, bx = 0

注意call dword ptr 会产生的几个push pop 会改变栈的值和sp的值


10.7  call 和 ret 的配合使用

利用call 和 ret 实现的子程序框架如下

assume cs:code
stack segment
	dw 8 dup (0)
stack ends

code segment		
main:	;
		;
		; call sub1
		;
		;
		mov ax, 4c00h
		int 21h

sub1:	;
		;
		; call sub2
		;
		ret

sub2:	;
		;
		ret
code ends

end main


10.8 mul指令

1) 两个相乘的数,要么都是8位。要么都是16位。 如果是8位一个默认在AL 另一个存放在8位reg 或内存字节单元中

如果是16位,一个默认中AX中,另一个放在16位reg或者内存字单元中

2)结果,如果是8位乘法,结果默认放在AX中; 如果是16位乘法,结果高位默认在DX,低位在AX中存放

mul reg

mul 内存单元


内存单元可以用不同的寻址方式

mul byte ptr ds:[0]

含义: (ax) = (al) * ((ds)*16 + 0)

mul word ptr [bx + si + 8]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值