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,下面这段代码会造成死循环。
1 ;一个死循环的例子 2 assume cs:codesg,ss:stack 3 4 stack segment 5 db 16 dup(0) 6 stack ends 7 8 codesg segment 9 10 mov bx,0 11 push bx 12 ;执行ret指令程序转到第一行开始执行 13 ret 14 mov ax,4c00h 15 int 21h 16 17 start: mov ax,stack 18 mov ss,ax 19 mov sp,16 20 mov ax,0 21 push cs 22 push ax 23 ;执行retf指令程序转到第一行开始执行 24 retf 25 26 codesg ends 27 end start 28 end
call指令有多形式:call 标号;call far ptr 标号;call reg;call word tr 内存单元;call dword tr 内存单元.
CPU执行call 标号相当于执行:
push IP
jmp near ptr 标号
ps:这里push IP是加上call 标号这条指令长度后的(IP)
CPU执行call far ptr 标号相当于执行:
push CS
push IP jmp far ptr 标号
ps:先进行push CS操作我觉得是因为retf指令先进行pop IP操作,以完成子程序的功能
CPU执行call reg相当于执行:
push IP
jmp reg
ps:reg特指16位寄存器
CPU执行call word ptr 内存单元相当于执行:
push IP
jmp word ptr 内存单元
CPU执行call dword ptr 内存单元相当于执行:
push CS
push IP
jmp dword ptr 内存单元
从ret和call的功能不难看出这两个指令是设计用来配合使用的,可以达到子程序的效果,和高级语言的函数很像,下面这段代码依然是死循环。
1 ;一个死循环的例子 2 assume cs:codesg,ss:stack 3 4 stack segment 5 db 16 dup(0) 6 stack ends 7 8 codesg segment 9 10 start: mov ax,stack 11 mov ss,ax 12 mov sp,16 13 call s 14 s: mov ax,offset s 15 push ax 16 ret 17 mov ax,4c00h 18 int 21h 19 codesg ends 20 end start 21 end
mul是乘法指令,有两种情况:
1.8位乘法,两个相乘的数都是8位则一个数放在al中,另一个放在8位reg或内存单元中,结果存储在ax中
2.16位乘法,两个相乘的数都是16位则一个数放在ax中,另一个放在16位reg或内存字节单元中,结果高位存储在dx中,地位存储在ax中
到目前为止,加减乘除四种基本运算指令都已经学过了,下面写个小程序做次总结。
1 ;基本的算数运算指令 2 assume cs:codesg 3 4 codesg segment 5 6 mov al,0 7 add al,2 8 mov cx,6 9 s: add al,al 10 loop s 11 ;al累加6次得结果128 12 13 mov bl,2 14 mul bl 15 ;8位数乘法,ax=0100h 16 17 mov bx,1000d 18 mul bx 19 ;16位乘法dx=0003h,ax=e800h 20 21 div bx 22 ;32除法,ax=0100h 23 24 mov bl,2 25 div bl 26 ;16除法,al=128 27 28 sub al,al 29 ;减法操作ax=0 30 31 codesg ends 32 33 end