1.call和ret指令都是转移指令,它们都修改IP的值,或同时修改CS和IP的值。它们经常共同用语实现子程序的设计。
2.ret指令用栈中的数据,修改IP的内容,从而实现近转移。
3.retf指令用栈中的数据,修改CS和IP的内容,从而实现远转移。
4.CPU执行ret指令时,
(1)(IP)=((ss)*16+(sp))
(2)(sp)=(sp)+2
相当于进行:pop IP
执行retf指令时,
(1)(IP)=((ss)*16+(sp))
(2)(sp)=(sp)+2
(3)(CS)=((ss)*16+(sp))
(4)(sp)=(sp)+2
相当于进行:
pop IP
pop CS
5.CPU执行call指令时,进行两步操作:
(1)将当前的IP或CS和IP压入栈中;
(2)转移(jmp)
6.call指令不能实现短转移,call指令实现转移的方法和jmp指令的原理相同。
7.call 标号(将当前的IP压栈后,转到标号处执行指令)
CPU执行此种格式的call指令时,进行如下的操作:
(1)(sp)=(sp)-2
((ss)*16+(sp))=(IP)
(2)(IP)=(IP)+16位位移
call执行"call标号"时,相当于进行:
push IP
jmp near ptr 标号
8."call far ptr 标号"实现的是段间转移.
CPU执行此种格式的call指令时,进行如下的操作:
(1)(sp)=(sp)-2
((ss)*16+(sp))=(CS)
(sp)=(sp)-2
((ss)*16+(sp))=(IP)
(2)(cs)=标号所在段的段地址
(IP)=标号在段中的偏移地址
CPU执行"call far ptr 标号"时,相当于进行:
push CS
push IP
jmp far ptr 标号
9.指令格式:call 16位 reg
功能:
(sp)=(sp)-2
((ss)*16+(sp))=(IP)
(IP)=(16位 reg)
CPU执行"call 16位 reg"时,相当于:
push IP
jmp 16 位 reg
10.转移地址在内存中的call指令有两种格式.
(1)call word ptr 内存单元地址
CPU执行"call word ptr 内存单元地址"时,相当于:
push IP
jmp word ptr 内存单元地址
(2)call dword ptr 内存单元地址
CPU执行"call dword ptr 内存单元地址"时,相当于:
push CS
push IP
jmp dword ptr 内存单元地址
11.利用call和ret可以实现子程序的机制,框架如下:
- assume cs:code
- code segment
- start :
- :
- :
- call sub1
- :
- :
- mov ax , 4c00h
- int 21h
- sub1 :
- :
- :
- call sub2
- :
- :
- ret
- sub2 :
- :
- :
- ret
- code ends
- end start
12.mul是乘法指令,使用mul做乘法的时候需注意一下两点.
(1)两个相乘的数:两个相乘的数,要么都是8位,要么都是16位.如果是8位,默认放在AL中,另一个放在8位的reg或内存字节单元中;
如果是16位,一个默认放在AX中,另一个放在16位reg过内存字单元中.
(2)结果:如果是8位乘法,默认放在AX中;如果是16位乘法,结果高位放在DX中,低位放在AX中.
格式如下:
mul reg
mul 内存单元
例如:
(1)计算100*10
mov al,100
mov bl,10
mul bl
结果:(AX)=1000(03E8H)
(2)计算100*10000
mov ax,100
mov bx,10000
mul bx
结果:(AX)=4240H,(DX)=000FH (F4240H=1000000)
13.call和ret指令共同支持了汇编语言编程中的模块化设计.
14.用寄存器来存储参数和结果是最常用的方法.
15.对于批量数据的传递,我们将它放在内存中,然后将它们所在内存控件的首地址放在寄存器中,传递给需要的子程序.(联想:C的指针和数组关系)
16.当出现寄存器冲突时(如多次使用CX),解决方法是在子程序的开始将子程序中所有用到的寄存器中的值都保存起来,在子程序返回前再恢复(栈的使用)