汇编语言(王爽)-第十章
第十章 CALL和RET指令
一、ret和retf
*ret:功能为:pop ip,实现的是段内近转移;相当于jmp near ptr X
*retf功能为:pop ip,pop cs,实现的是远转移;相当于jmp far ptr X
二、 call指令
*call指令分为两步:
(1)将当前IP压入栈;
(2)设置新IP进行转移。
1、依据位移进行转移的call指令
call 标号,功能为:
push IP
jmp near ptr 标号
可看出call的转移操作与jmp near ptr一样,均使用位移进行,位移量为16位。
2、直接使用转移目的地址的call指令
(1)转移目的地址在指令中的call指令:call far ptr 标号
其功能为:
push CS
push IP
jmp far ptr 标号
(2)转移目的地址在寄存器中的call指令:call reg(16位)
其功能为:
push IP
jmp reg(16位)
(3)转移目的地址在内存中的call指令
a. call word ptr 内存单元地址
其功能为:
push IP
jmp word ptr 内存单元地址
b. call dword ptr 内存单元地址
其功能为:
push CS
push IP
jmp dword ptr 内存单元地址
检测点10.5
(1)下面程序执行后,ax中数值为多少?
assume cs:code stack segment dw 8 dup (0) stack ends code segment start: mov ax,stack ;A mov ss,ax mov sp,16 mov ds,ax mov ax,0 ;B call word ptr ds:[0eh] ;C inc ax ;D inc ax inc ax mov ax,4c00h int 21h code ends end start ;第一次从A开始执行,此时栈段内数值均为0, ;运行到C时,先将D处的IP压入stack段,再取出ds:[0eh]处的字数值作为IP ;而此时该处数值就为之前压入的D处的IP ;所以继续执行D,直到结束。(AX)=3
(2)下面程序执行后,ax和bx中数值为多少?
assume cs:code data segment dw 8 dup (0) data ends code segment start: mov ax,data ;A mov ss,ax mov sp,16 mov word ptr ss:[0],offset s ;B mov ss:[2],cs ;C call dword ptr ss:[0] ;D nop ;Nop s: mov ax,offset s ;E sub ax,ss:[0ch] ;F mov bx,cs ;G sub bx,ss:[0eh] ;H mov ax,4c00h int 21h code ends end start ;B句把标号s的偏移地址复制到ss:[0]处 ;C句把cs复制到ss:[2] ;到D句时候,先将Nop句的CS和IP分别压入栈,对应(ss:0eh)=(CS),(ss:0ch)=(IP) ;再跳转到对应位置,即s处继续执行 ;E句给ax赋值标号s的偏移地址 ;F句用ax的值减去ss:[0ch];即用E处的偏移地址减去Nop的偏移地址 ;即为NOP的代码长度,即(ax)=1. ;同理分析G,H,(bx)=0
三、mul指令
1、对于8位×8位运算
其中一个乘数默认在al中,另外一个乘数在8位reg或内存单元中,结果为16位,存在ax中;
2、对于16位×16位运算
其中一个乘数默认在ax中,另外一个乘数在16位reg或内存单元中,结果为32位,高位存在dx,低位存在ax中;
四、模块化程序设计
1、call和ret使得汇编编程中模块化设计的实现;主程序中使用call,暂存主程序中下一指令的地址(IP入栈),同时
调用子程序;子程序中使用ret/retf指令取出前面缓存的主程序指令ip(出栈),返回主程序;
2、参数的使用:对于子程序而言,无法得知可能会调用其的主程序的寄存器使用情况,所以一般情况下,子程序先需要将
用到的寄存器入栈保护,在ret/retf返回前在出栈调出原寄存器值。