汇编语言ret与call指令

CALL和RET指令

ret和retf

  1. ret指令用栈的数据,修改IP的内容,实现近转移

简而言之,就是从栈中弹出一个数值给IP

  1. retf指令用栈的数据,修改CS和IP的内容,实现远转移

简而言之,就是从栈中依次弹出两个分别给CS和IP

call指令

根据位移进行转移

call 标号

  1. 将当前IP或CS和IP压入栈中
  2. 转移

相当于:

push IP
jmp nera ptr 标号

在此时栈中存储call指令之后下一条指令的IP,如:

assume cs:code 
stack segment
    db 16 dup(0)
stack ends
code segment
start:  mov ax,0     ;0E25:0000   
        call s       ;0E25:0003
        inc ax       ;0E25:0006
    s:  pop ax       ;0E25:0007

code ends
end start

pop ax:得到ax=0006 (call下一条指令的IP)

转移目的地址在指令中

call far ptr 标号

实现段间转移
相当于

push CS
push IP
jmp far ptr 标号

此时,栈中存储CS和IP:

assume cs:code
code segment
start:  mov ax,0          ;1000:0
        call far ptr s    ;1000:3
        inc ax            ;1000:8          
    s:  pop ax            ;1000: 9
        add ax,ax
        pop bx
        add ax,bx
code ends
end start

call far ptr s:执行后,push CS,push IP,jmp s => ax=IP=8,bx=CS=1000

转移地址在寄存器中

call 16位 reg

相当于:

push IP
jmp 16位reg(寄存器)

把IP入栈后,跳转到标号寄存器中:

assume cs:code
code segment
start:  mov ax,9       ; 1000:0
        call ax        ; 1000:3

        inc ax
        inc ax
        mov bp,sp
        add ax,[bp]
code ends
end start

开始时ax=9,执行call ax后,把IP=3入栈,之后跳转到IP=0009(即ax的偏移地址)处

转移地址在内存中

call word ptr 内存单元地址

相当于:

push IP
jmp word ptr 内存单元地址

转移到内存单元地址:
IP:

assume cs:code
code segment
start:  mov sp,10h
        mov ax,0123h
        mov ds:[0],ax
        call word ptr ds:[0]

code ends
end start

执行完毕后:IP=0123 SP=0EH

CS和IP:

assume cs:code
code segment
start:  mov sp,10h
        mov ax,0123h
        mov ds:[0],ax
        mov word ptr ds:[2],0    ;23 01 00 00
        call dword ptr ds:[0]    ;双字节,CS=0000 IP=0123

code ends
end start

执行完毕后:CS=0000 IP=0123 SP=0EH

使用call和ret来编写子程序

call指令:可以将IP或者CS和IP压入栈中
ret指令:将IP弹出栈
利用他们入栈出栈的机制可以实现一个子程序的编写,例如:
在主程序中用call去跳转到一个子程序,call保存之后的偏移地址IP,将其压入栈中,以便能够执行完子程序之后返回,call之后,跳转到子程序标号,执行子程序,执行完毕后,使用ret弹出IP栈值,这时的IP指向call之后的地址,因此会跳转回call之后的下一条指令,重新指向主程序。

assume cs:code
code segment
start:  mov ax,1
        mov cx,3
        call s          ;1000:0006
        mov bx,ax       ;1000:0009
        mov ax,4c00h
        int 21h
    s:  add ax,ax       ;1000:0010
        loop s
        ret
code ends
end start

分析:主程序call s的IP地址为06,首先将call的下一条指令的IP压入栈中push IP,之后跳转到s标号处,执行cx次add ax,ax 之后ret指令将pop IP,此时的IP为之前压入栈中的IP,IP=09,所以再次执行mov bx,ax,直到程序结束

posted @ 2022-09-10 22:34  hugeYlh  阅读(41)  评论(0编辑  收藏  举报  来源