• 8086汇编之 CALL 和 RET指令


    Ret 和 call 也是转移指令,可是他们跟jmp不同的是,这两个转移指令都跟栈有关系。

    <1> ret

    用栈中的数据改动IP的地址,从而实现近转移

    ( ip ) = ( (ss)*16+ sp )

    ( sp ) =( sp ) + 2

    相当于pop ip

    <2>retf

    用栈中的数据来改动CS以及IP的值,实现段间转移

    ( ip ) = ( (ss)*16+ sp )

    ( sp ) =( sp ) + 2

    ( cs ) = ( (ss)*16+ sp )

    ( sp ) =( sp ) + 2

    相当于

    Pop ip

    Pop cs

    <3> call xxx(行号)

    先把当前IP压栈,然后跳转,相当于实现近转移

    ( sp ) = ( sp ) – 2

    ( (ss)*16+ sp ) = ( ip )

    ( ip ) = ( ip ) + 16位位移

    相当于:

    Push ip

    Jmp near ptr xxx(行号)

    <4>call far ptr

    把CS。IP压栈处理,然后实现跳转,相当于段间转移。远转移

    ( sp ) = ( sp ) – 2

    ( (ss)*16+ sp ) = ( cs )

    ( sp ) = ( sp ) – 2

    ( (ss)*16+ sp ) = ( ip )

    (cs) = 当前行号段地址

    (ip) = 当前行号偏移地址

    相当于:

    Push cs

    Push ip

    Jmp far ptr xxx

    <5> call reg(16bit)

    跳转到16位寄存器上中存储的地址

    ( sp ) = (sp) – 2

    ( (SS)*16 + (sp) ) = (IP)

    (IP) = ( 16bit Reg )

    相当于:

    Push IP

    Jmp 16bit Reg

    <6> call word ptr 内存单元地址

    相当于

    Push IP

    Jmp word ptr 内存单元地址

    如:call word ptr ds:[0]

    <7> call dword ptr 内存单元地址

    相当于

    Push cs

    Push ip

    Jmp dword ptr 内存单元地址

    比如:jmp dword ptr DS:[0];

    <8>寄存器的冲突问题

    主程序调用子程序段的时候,可能子程序会用到主程序中使用的寄存器的值。程序在设计的时候不可能做到不让子程序使用主程序的寄存器,由于两者是相互独立的。你永远不会还有一个会做什么。所以在子程序中採取不使用主程序中调用的寄存器的做法是不可行的。

    解决方法:

    把寄存器用到的东西,保存到堆栈里面。子程序调用完成。再将堆栈保存的东西弹出。

  • 相关阅读:
    第四讲动手动脑集课后作业
    第三讲课后作业
    课后作业01
    《大道至简》第一章伪代码读后感
    第八周学习进度条
    第七周学习进度条
    求一维联通数组的最大子数组之和
    求二维数组的最大联通子数组之和
    第六周学习进度条
    求一个数组的最大子数组之和
  • 原文地址:https://www.cnblogs.com/jhcelue/p/7295724.html
Copyright © 2020-2023  润新知