CSAPP,即《深入理解计算机系统:程序员视角》第三版,是一本好书,但读起来确需要具备相当的基本功。而且,有的表述(中译文)还不太直白。

  比如,第463页提到,(对于32位系统)为什么汇编器会将call指令中的引用的初始值设置为-4。其后解释语焉不详。结合文中对代码计算公式的展开:

*refptr = (unsigned) (ADDR(r.symbol) + *refptr - refaddr)

= (unsigned) (0x80483c8        + (-4)     - 0x80483bb)

= (unsigned) (0x9)

依然一头雾水。

  其实,这里只要反过来推算,就很好理解了。下图是重定向完成后的内存映象:

0x80483b4    .text

...

0x80483ba    call 80483c8<swap>    ; e8 09 00 00 00

0x80483bb --↗

0x80483bf    (下一条指令)

...

0x80483c8    swap()

...

  有题如下:

  已知:.text节重定位于0x80483b4,相应地call调用则位于0x80483ba,而swap()函数重定位于0x80483c8。

  求:重定位后,call指令的操作码(即书中所谓“重定位引用”)应当是几?(亦即swap函数相对于call指令执行时PC的偏移是多少?)

  首先说答案,swap函数相对于call指令执行时PC的偏移是0x9,即call指令的完整机器码是 e8 09 00 00 00。

  为什么呢?因为当执行call指令时,PC值已是下一条指令的地址即0x80483bf。为了完成call调用,要把PC值加上call的操作数,结果作为新的PC值。也就是 0x80483bf + 0x9 = 0x80483c8,正好是swap()函数的地址。

  接下来说说,call指令中的引用的初始值-4是做什么用的。我把前面的公式变形:

*refptr = (unsigned) (ADDR(r.symbol) + *refptr - refaddr)

= (unsigned) (ADDR(r.symbol) + (*refptr - refaddr))

= (unsigned) (0x80483c8        + (-4      - 0x80483bb))

= (unsigned) (0x80483c8        -0x80483bf)

= (unsigned) (0x9)

  可以看到,-4就是为了从call指令中操作数本身的地址转换为下一指令的地址而设置的。对于32位机器来说,call指令长5字节,操作码1个字节,而操作数正好占4字节。call指令位于0x80483ba,操作数位于0x80483bb,再过4字节就正好是下一条指令的地址。

  那为什么用-4而不是+4呢?其实很简单,这和链接程序采用的计算公式有关。

  

CSAPP读书随笔之一:为什么汇编器会将call指令中的引用的初始值设置为-4的更多相关文章

  1. csapp读书笔记-并发编程

    这是基础,理解不能有偏差 如果线程/进程的逻辑控制流在时间上重叠,那么就是并发的.我们可以将并发看成是一种os内核用来运行多个应用程序的实例,但是并发不仅在内核,在应用程序中的角色也很重要. 在应用级 ...

  2. PyQt(Python+Qt)学习随笔:Qt Designer组件属性编辑界面中对话窗QDialog的modal属性

    modal属性表示窗口执行show()操作时是以模态窗口还是非模态窗口形式展示,缺省为False,设置该值与QWidget.windowModality的值设置为 Qt.ApplicationModa ...

  3. CSAPP 读书笔记 - 2.31练习题

    根据等式(2-14) 假如w = 4 数值范围在-8 ~ 7之间 2^w = 16 x = 5, y = 4的情况下面 x + y = 9 >=2 ^(w-1)  属于第一种情况 sum = x ...

  4. 锋利的jQuery读书随笔

    代码规范:var $variable = jQuery对象:var variable = DOM对象: jQuery对象无法使用DOM对象的任何方法,同样DOM对象也无法使用jQuery对象的任何方法 ...

  5. CSAPP读书笔记--第八章 异常控制流

    第八章 异常控制流 2017-11-14 概述 控制转移序列叫做控制流.目前为止,我们学过两种改变控制流的方式: 1)跳转和分支: 2)调用和返回. 但是上面的方法只能控制程序本身,发生以下系统状态的 ...

  6. FineUIMvc随笔(6)对比WebForms和MVC中表格的数据库分页

    声明:FineUIMvc(基础版)是免费软件,本系列文章适用于基础版. 通过对比WebForms和MVC中表格数据库分页代码的不同,可以对 MVC 中的数据流转有更加深入的了解. WebForms 中 ...

  7. PyQt学习随笔:重写setData方法截获Model/View中视图数据项编辑的注意事项

    根据<PyQt学习随笔:Model/View中视图数据项编辑变动实时获取变动数据的方法>可以重写从PyQt的Model类继承的setData方法来实时截获View中对数据的更改,但需要注意 ...

  8. [小菜随笔]新手使用appium+python进行自动化测试过程中webdriver.Remote报错的错误分析方法(带实例)

    很多人刚开始使用python+appium去执行APP自动化的时候经常会遇到webdriver.Remote,报错位置指向都是driver = webdriver.Remote('http://127 ...

  9. 工作随笔——Java调用Groovy类的方法、传递参数和获取返回值

    接触Groovy也快一年了,一直在尝试怎么将Groovy引用到日常工作中来.最近在做一个功能的时候,花了点时间重新看了下Java怎么调用Groovy的方法.传递参数和获取返回值. 示例Groovy代码 ...

随机推荐

  1. 郑捷《机器学习算法原理与编程实践》学习笔记(第四章 推荐系统原理)(二)kmeans

    (上接第二章) 4.3.1 KMeans 算法流程 算法的过程如下: (1)从N个数据文档随机选取K个文档作为质心 (2)对剩余的每个文档测量其到每个质心的距离,并把它归到最近的质心的类 (3)重新计 ...

  2. python中的时间转换

    Python中的时间相关库有: datetime 和time. 主要形式有: datetime timestamp 相互转换: timestamp->datetime: dt = datetim ...

  3. DOS基本命令及其详解

    指令格式:命令 选项 参数命令:要求计算机做某操作,可以是系统中的某个可执行程序,也可以是内存中的某函数.接口.别名等.如果是可执行程序,默认要带路径执行,除非该路径配置在环境变量path中.选项:表 ...

  4. 使用merge同时执行insert和update操作

    SQL点滴18—SqlServer中的merge操作,相当地风骚   今天在一个存储过程中看见了merge这个关键字,第一个想法是,这个是配置管理中的概念吗,把相邻两次的更改合并到一起.后来在tech ...

  5. python实践——批量统计mongodb数据库的集合大小

    #!/usr/bin/env python import os,sys list = [] for i in range(3,50): l = os.popen("/bin/echo 'sh ...

  6. php_access_ADOConn 备忘

    1.咕~~(╯﹏╰)b 各种乱码. 2.本来是MFC+Access 用msado15.dll写的系统,闲的想用php改改. Demo.php <meta http-equiv="Con ...

  7. 网络-->监控-->单位换算

    The metric system In some cases when used to describe data transfer rates bits/bytes are calculated ...

  8. MVC拦截器记录操作用户日志

    主要是用于记录用户操作动态, public class OperationAttribute:ActionFilterAttribute { /// <summary> /// 方法名称 ...

  9. Java线程池入门

    序 为什么要用线程池?什么情况下才会用到线程池? 并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统的效率,因为频繁创建线程和销毁线程需要时间. 因此 ...

  10. Asp.Net MVC4入门指南(6):验证编辑方法和编辑视图

    在本节中,您将开始修改为电影控制器所新加的操作方法和视图.然后,您将添加一个自定义的搜索页. 在浏览器地址栏里追加/Movies, 浏览到Movies页面.并进入编辑(Edit)页面. Edit(编辑 ...