第十章 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 IPjmp near ptr 标号可看出call的转移操作与jmp near ptr一样,均使用位移进行,位移量为16位。2、直接使用转移目的地址的call指令(1)转移目的地址在指令中的call指令:call far ptr 标号其功能为:push CSpush IPjmp far ptr 标号(2)转移目的地址在寄存器中的call指令:call reg(16位)其功能为:push IPjmp reg(16位)(3)转移目的地址在内存中的call指令a. call word ptr 内存单元地址其功能为:push IPjmp word ptr 内存单元地址b. call dword ptr 内存单元地址其功能为:push CSpush IPjmp dword ptr 内存单元地址检测点10.5
(1)下面程序执行后,ax中数值为多少?
assume cs:codestack segment dw 8 dup (0)stack endscode segmentstart: 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 21hcode endsend start ;第一次从A开始执行,此时栈段内数值均为0,;运行到C时,先将D处的IP压入stack段,再取出ds:[0eh]处的字数值作为IP;而此时该处数值就为之前压入的D处的IP;所以继续执行D,直到结束。(AX)=3
(2)下面程序执行后,ax和bx中数值为多少?
assume cs:codedata segment dw 8 dup (0)data endscode segmentstart: 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 ;Nops: mov ax,offset s ;E sub ax,ss:[0ch] ;F mov bx,cs ;G sub bx,ss:[0eh] ;H mov ax,4c00h int 21hcode endsend 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返回前在出栈调出原寄存器值。