• 汇编语言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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    开始时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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    执行完毕后: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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    执行完毕后: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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

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

  • 相关阅读:
    设计模式 - 中介者模式
    pytorch里面的 nn.Parameter 和 tensor有哪些异同点
    Centos7 docker 容器内root身份应用自启动 & /usr/sbin/init 问题
    全网最全JAVA面试八股文,终于整理完了
    Dynamic CRM插件中记录日志-Nlog记录到文本
    MySQL学习笔记(九)MVCC
    独立机器连接cdh的spark集群,远程提交任务(绝对可以成功,亲测了n遍)
    pytest + yaml 框架 -62.支持yaml和json2种格式用例
    申请CNAS软件测试资质,如何选择测试工具最具性价比?
    Spark 离线开发框架设计与实现
  • 原文地址:https://blog.csdn.net/jj6666djdbbd/article/details/126800429