RET和RETF指令
RET
CPU执行RET指令时,进行下面两步操作:
- 用
SS:SP
指向内存字单元中的数据修改 IP 寄存器 - SP 的值增加2
(换句话说,CPU执行 RET 指令时,相当于进行“ POP IP
”操作)
RET
CPU执行 RETF 指令时,进行下面两步操作:
- 用
SS:SP
指向内存字单元中的数据修改 IP 寄存器 - SP 的值增加2
- 再次用
SS:SP
指向内存字单元中的数据修改 CS 寄存器 - SP 的值增加2
(换句话说,CPU执行 RETF 指令时,相当于进行“ POP IP
”和“ POP CS
”操作)
CALL指令
CALL
label
CPU进行 CALL 指令时,进行两步操作:
- 将当前的 IP ,或 CS 和 IP 压入栈中
- 转移
(换句话说,CPU相当于执行“ PUSH IP
”和“ JMP near ptr label
”)
CALL 指令不能实现短转移,除此之外 CALL 指令实现转移的方式与和 JMP 指令相同。主要应用格式还有:
CALL far ptr label
该格式实现的是段间转移,CPU执行此种格式的指令时,进行如下操作:
- SP 的值减少2
- 用
SS:SP
指向内存字单元中的数据修改 CS 寄存器 - SP 的值减少2
- 再次用
SS:SP
指向内存字单元中的数据修改 IP 寄存器
(换句话说,CPU相当于执行“ PUSH CS
”、“ PUSH IP
”和“ JMP far ptr label
”操作)
CALL 16bit-reg
将当前的 IP 压栈后,转到16位寄存器 16bit-reg
值代表的偏移地址处执行指令。
(换句话说,CPU相当于执行“ PUSH IP
”和“ JMP 16bit-reg
”)
CALL word ptr memory
将当前的 IP 压栈后,转到内存字单元的值代表的偏移地址处执行指令。
(换句话说,CPU相当于执行“ PUSH IP
”和“ JMP word ptr memory
”)
内存单元地址可用寻址方式的任意格式给出。
JMP dword ptr memory
将当前的 CS 和 IP 压栈后,转到内存双字单元的值代表的物理地址处执行指令。高地址处存放的字是物理地址的段地址,低地址处存放的字是物理地址的偏移地址。
(换句话说,CPU相当于执行“ PUSH CS
”、“ PUSH IP
”和“ JMP dword ptr memory
”)
内存单元地址可用寻址方式的任意格式给出。
CALL和RET的配合使用
CALL 和 RET 指令经常配合使用,用来实现子程序的设计,即具有一定功能的程序段。
在需要使用的时候,可以用 CALL 指令转去执行,此时 CALL 指令后面指令的地址将存储在栈中。
执行完子程序后,可以在子程序后面使用 RET 指令,用栈中的数据设置 IP 的值,从而转到 CALL 指令后面的代码处继续执行。
这样,可以利用 CALL 和 RET 来实现子程序的设计。子程序的框架为:
; ...code...
RET
这样,具有子程序的源程序的框架为:
codes segment
main:
; ...code...
CALL sub1
; ...code...
mov ax, 4c00h
int 21h
sub1:
; ...code...
CALL sub2
; ...code...
RET sub2:
; ...code...
RET ; ...code...
codes ends
end main
以下示例程序使用子程序的方式来计算阶乘:
在寄存器 CX 中移入不同的值,即可计算不同次方的阶乘。
MUL指令
MUL
container
两个相乘的数,要么都是8位,要么都是16位:
- 如果都是8位,一个默认放在 AL 中,另一个放在
container
对应的8位reg
- 如果都是16位,一个默认放在 AX 中,另一个放在
对应的16位container
reg
或内存字单元中。
内存单元地址可用寻址方式的任意格式给出。
乘法运算的结果:
- 如果是8位乘法,则结果默认放在 AX 寄存器中;
- 如果是16位乘法,则结果高位默认放在 DX 寄存器中,低位默认放在 AX 寄存器中。