前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >ret指令与call指令的深入理解

ret指令与call指令的深入理解

作者头像
Elapse
发布2020-08-17 11:39:28
4.2K0
发布2020-08-17 11:39:28
举报
文章被收录于专栏:E条咸鱼E条咸鱼

本篇原创作者: Rj45

背景

1、代码

2、编译

代码语言:javascript
复制
gcc Rj45.c -o Rj45 -m32

3、反编译

代码语言:javascript
复制
objdump -d Rj45 -M intel
代码语言:javascript
复制
0804840b <main>:
 804840b:    8d 4c 24 04             lea    ecx,[esp+0x4]
 804840f:    83 e4 f0                and    esp,0xfffffff0
 8048412:    ff 71 fc                push   DWORD PTR [ecx-0x4]
 //从上述汇编代码可以看到,在底层中,main函数并不如我们接触的编程语言一样,为程序运行时第一个执行函数,还有函数在main函数前执行。
 8048415:    55                      push   ebp
 8048416:    89 e5                   mov    ebp,esp
 8048418:    51                      push   ecx
 8048419:    83 ec 04                sub    esp,0x4
 804841c:    83 ec 0c                sub    esp,0xc
 804841f:    68 c0 84 04 08          push   0x80484c0//压入参数`hello,Rj45`所存储的地址
 8048424:    e8 b7 fe ff ff          call   80482e0 <puts@plt>//调用puts函数进行打印
 8048429:    83 c4 10                add    esp,0x10//进行栈帧平衡
 804842c:    b8 00 00 00 00          mov    eax,0x0
 8048431:    8b 4d fc                mov    ecx,DWORD PTR [ebp-0x4]
 8048434:    c9                      leave
 8048435:    8d 61 fc                lea    esp,[ecx-0x4]
 8048438:    c3                      ret    //puts函数返回
 8048439:    66 90                   xchg   ax,ax
 804843b:    66 90                   xchg   ax,ax
 804843d:    66 90                   xchg   ax,ax
 804843f:    90                      nop

4、问题 在反汇编的过程中,有两个比较关键的地方:callret

在《汇编语言(第3版)》中对这两个指令的概述为:

代码语言:javascript
复制
call和ret指令都是转移指令,它们都修改IP,或同时修改CS和IP。它们经常被共同用来实现子程序的设计,也即是调用和返回。

其中ret指令用栈中的数据,修改IP的内容,实现近转移。而call指令将IP或者CS和IP压入栈中,实现转移。还有retf指令,用栈中的数据,修改CS和IP的内容,实现远转移。

那么,如何理解这个概述,以及如何理解从概述延申出来的概念性的知识

什么是转移指令?

1、概念 转移指令是可以控制CPU执行内存中某处代码的指令,或者说,转移指令是可以修改IP,或同时修改CS和IP的指令。

根据转移行为可分为段内转移和段间转移,其中 只修改IP的叫段内转移;同时修改CS和IP的,叫段间转移

由于转移指令对IP或CS和IP的修改范围的不同,又分为短转移、近转移和远转移。

2、分类

代码语言:javascript
复制
无条件转移指令,如jmp
条件转移指令,如jz
循环指令,如loop
过程
中断

什么是CS和IP?

CS是代码段寄存器、IP是指令指针寄存器。

(8086CPU有四个段寄存器,CS、DS、SS、ES,当CPU要访问内存是由这四个段寄存器提供内存单元的段地址。)

这两个寄存器是8086CPU中最关键的寄存器,它们指示了CPU当前要读取指令的地址。

CS和IP如何指示CPU读取指令的地址?

8086机器中,任意时刻,CPU将CS:IP指向的内容当作指令执行。

意思是,任意时刻,设CS中的内容是M,IP中的内容为N,8086CPU将从内存M*16+N单元开始,读取一条指令并执行。

解释:CPU当前的状态是CS内数据为2000H,IP内为0000H

内存20000到20009H单元存放着可执行的机器码

1、CPU将从内存2000H*16+0000H出读取指令执行,其中将CS和IP内容送入地址加法器,地址加法器完成后,得到 物理地址=段地址*16+偏移地址

2、地址加法器将物理地址送人输入输出控制电路,输入输出控制电路将物理地址20000H送上地址总线。

3、从内存20000H单元开始存放的机器指令 B82301即mov ax,0123H通过数据总线被送入CPU。

4、输入输出控制电路将机器指令送入指令缓冲器,接着到执行控制器。执行控制器执行指令后,AX内的内容为0123H。

5、读取一条指令后,IP中的值会自动增加,以使CPU可以读取下一个指令。因当前读取的指令 B82301的长度为3,故IP的值加3,CS:IP指向内存单元2000:0003。

6、以此依次执行。

什么是段地址和偏移地址?

什么是段?段的划分来自于CPU,而不是内存,内存没有分段。

由于8086CPU的内存的物理地址=段地址*16+偏移地址,故使得在管理内存的时候借助了分段的概念,将若干个地址连续的内存单元看作一个段。

什么是段地址和偏移地址?这是8086CPU对内存读写图

CPU的两个相关部件提供两个16位地址、段地址和偏移地址。

段地址和偏移地址通过内部总线送到地址加法器。

地址加法器通过 物理地址=段地址\*16+偏移地址,合成20位物理地址。

输入输出电路将物理地址送上地址总线。故段地址和偏移地址也即CS内地址数据和IP内地址数据。

ret指令与call指令实现了什么功能?

1、ret指令用栈中的数据,修改IP的内容,返回代码段的第一条指令。相当于

代码语言:javascript
复制
pop IP

2、call指令将IP或者CS和IP压入栈中,实现转移。相当于

代码语言:javascript
复制
push IP
//push IP和push CS
jmp [address]

3、retf指令,用栈中的数据,修改CS和IP的内容,返回代码段的第一条指令。相当于

代码语言:javascript
复制
pop IP
pop CS

以ret和call实现的子程序源程序的框架

代码语言:javascript
复制
assume cs:code
code segment
    main:   :
            :
            call sub1//调用子程序sub1
            :
            mov ax,4c00h
            int 21h
    sub1:   :
            :
            call sub2//调用子程序sub2
            :
            ret//子程序返回
    sub2:   ://子程序sub2开始
            :
            ret//子程序返回
code ends
end main

解释:一个写有一定功能的程序段叫子程序。在子程序需要被执行的时候用call指令去调用。当子程序执行完后,由于call指令后面的指令的地址已经存储在栈中( push操作), 使得在子程序后面再使用ret指令时候,栈中的数据会设置IP内的值, IP内的值的设置实现了CPU继续执行call指令后面的代码指令,达到程序继续执行的目的。

参考

《汇编语言(第3版)》

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-09-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 E条咸鱼 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 本篇原创作者: Rj45
  • 背景
  • 什么是转移指令?
  • 什么是CS和IP?
  • CS和IP如何指示CPU读取指令的地址?
  • 什么是段地址和偏移地址?
  • ret指令与call指令实现了什么功能?
  • 以ret和call实现的子程序源程序的框架
  • 参考
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档