call指令和ret指令【笔记+详解】 您所在的位置:网站首页 rep指令作用 call指令和ret指令【笔记+详解】

call指令和ret指令【笔记+详解】

2024-07-10 19:13| 来源: 网络整理| 查看: 265

笔记目录 call指令和ret指令【笔记】1 引子2 call和ret的简单运用3 call指令本质含义详解4 ret指令5 总结及汇编环境资源

call指令和ret指令【笔记】 1 引子

   在高级语言中,常有主程序调用其他子程序,子程序还可以调用子程序…,比如在C语言中,在main主函数里调用cube函数,该函数被执行完后返回main函数,然后程序继续往下执行,如下:

#include int main(){ int cube();//函数的声明 int a = cube();//调用函数 ... return 0; } //定义函数 int cube(){ printf("hello"); return 10; }

  在汇编语言中也有类似的这种机制,能实现主程序调用子程序。这就要使用call和ret汇编指令

2 call和ret的简单运用

2.1功能简述:   call指令可以实现调用一个子程序,在子程序里使用ret指令结束子程序的执行并返回主程序(类比C语言中的main函数调用cube函数进行理解),主程序继续往下执行。

2.2指令格式:

call 标号 或者call far 标号ret 或者 ret n

2.3标号位数:

16位位移=”标号所在偏移地址“ - call指令的下一条指令的偏移地址16位位移的范围"-32768~32767",补码表示

2.4示例:(”;“符号是8086汇编的注释符)

... mov ax,0 call s ;s是标号,执行call后,执行s标号所在的子程序 mov ax,4c00h int 21h s:add ax,1 ;标号所在子程序 mov bx,10 ret ;子程序执行完后,返回主程序 3 call指令本质含义详解

3.1实质:call指令是一个流程转移指令,就是让程序执行的顺序发生短暂的改变,去执行别处地址上的指令,遇到ret指令后再回到原来的地方继续往下顺序执行,本质和jmp大同小异,区别是在jmp基础上增加了程序回到原来跳转处的功能。

3.2call执行步骤:(cpu执行call指令)

第一步:将当前的ip或者cs和ip压入栈中。即跳转前保存call指令的下一条指令的首地址第二步:转移到标号处执行子程序。即修改ip或者cs和ip里的内容(对比jmp详解篇理解)

第一步分析: 先看一个汇编源程序

assume cs:code,ss:stack stack segment db 8 dup (0) stack ends code segment start: mov ax,stack mov ss,ax mov sp,8 call s mov ax,0 mov ax,4c00h int 21h s: mov bx,0 add bx,1 ret code ends end start

编译后对应的机器码和汇编指令 知道call指令的下一条指令的偏移地址是000B,即取call指令完后ip的内容就为000B,紧接着执行call指令,由第一步知晓执行call指令时,当前的ip或者cs和ip压入栈中。 (备注:cpu执行一条指令分为两步(t命令):1.取指令、2.执行指令) 我们再来看一下执行call指令之前栈段里的内存情况 在这里插入图片描述 此时栈里发现有数据(p指针左边的一个字的数据是”01A3“,这个数当作随机数处理)先不管这些数据,我们看到ip的值为”0008“,到目前为止只是执行call指令之前的代码,并未对栈里添加数据。接下来我们执行call指令,然后再观察栈顶数据,如下 在这里插入图片描述 发现栈顶的数据已经变为000B(这地址是call指令的下一条指令首地址,上文提到过),可能会想入栈的数据不是执行call指令时,当前的ip(图2中绿色划线)或者cs:ip(这里不讨论该种情况)的内容吗?,但别忘了,执行一条指令后,本该就要执行下一条指令(即ip=ip+指令长度,所对应的指令的,它就是call的下一条指令,因此ip变为000B),ip自增后发现执行的是call指令,然后进行第一步的入栈操作。(call指令还未完全执行)

接着分析第二步:   此时ip=000B,按理来说要执行ip=000B处的指令,但call指令的目的不就是使指令跳转吗,因此它还要修改ip为目的地的偏移地址,所以ip=0013(标号或目的地所在的偏移地址)。从而call指令实现,当前地址的保存(实质是下一条指令的首地址入栈)和程序的跳转。

4 ret指令

  理解call指令,ret指令就很容易明白,执行ret指令时,会把栈中原先存入的地址出栈,并送入到ip寄存器里,ret指令等价于”pop ip“的效果(没有pop ip这样的指令,是非法的)

5 总结及汇编环境资源 指令格式示例call 标号-仅仅修改ip,修改范围一个字call 16位寄存器-等价于call 标号call far ptr 标号-同时修改cs和ip,段间转移(调用子程序),先把cs入栈再把ip入栈call word ptr 内存单元地址-仅修改ip,段内转移,例如:… ptr ds:[idata]call dword ptr 内存单元地址-同时修改cs和ip,段间转移,先把cs入栈再把ip入栈,例如:…ptr ds:[idata]会把以idata为起始地址,长度为两个字的内存单元取出来,低地址的字单元存放偏移地址,高地址的字单元存放段地址。ret-把原先压入栈的ip内容进行出栈,并送入ip中,等价于pop ipretf-把原先压入栈的cs和ip出栈,同时修改ip和cs,先修改出栈ip再出栈cs,等价于:– pop ip– pop csret n- n是任意取的数字,一般n为栈中除开ip或者cs和ip数据外的其他数据占用的字节单元数,表示忽略栈中的数据,把栈顶指针移动到栈底。

(备注:没有pop ip这样的指令,是非法的,笔记中仅是为了方便理解而使用)

8086汇编环境资源免费获取【DOSBox】 链接:https://pan.baidu.com/s/1aRv4k6DVlJtGkHQDB6WjrA 提取码:8086



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有