Charpter Three 程序的机器级表示

  • 3.2 程序编码
    • 3.2.1 机器级表示
      • 抽象
        • 计算机系统使用了多种不同形式的抽象, 利用更简单的抽象模型来隐藏实现的细节
        • 最重要的两种抽象:
          1. 由指令集体系结构(Instruction Set Architecture, ISA)来定义机器级程序的格式和行为.
          2. 机器级程序使用的内存地址是虚拟地址, 提供的内存模型看上去是一个非常大的字节数组
      • 处理器状态
        • 程序计数器(通常被称为"PC", 在x86-64中用%rip表示): 给出将要执行的下一条指令在内存中的地址
    • 3.2.2 代码示例
      • 汇编与反汇编程序
        • 汇编: gcc
          • linux> gcc -Og -S mstore.c
            • 这会使GCC运行编辑器, 产生一个汇编文件mstore.s, 但是不做其他进一步的工作. (通常情况下, 它还会继续调用汇编器产生目标代码文件)
          • linux> gcc -Og -c mstore.c
            • 这会产生目标代码文件mstore.o, 它是二进制格式的, 所以无法直接查看
        • 反汇编: objdump
          • linux> objdump -d mstore.o
            • 这些反汇编程序(像objdump)会根据机器代码产生一种类似汇编代码的格式
      • 链接器
        • l链接器(Linker)是一个程序, 将一个或多个由编译器或汇编器生成的目标文件外加库链接为一个可执行文件
    • 3.2.3 关于格式的注释
      • 以"."开头的行
        • 都是指导汇编器和链接器工作的伪命令
      • 把C语言和汇编语言结合起来
        • 方法:
          1. 我们可以编写完整的函数, 放进一个独立的汇编文件中, 让汇编器和链接器把它和用C语言编写的代码合并起来
          2. 我们可以使用GCC的内联汇编(inline assembly)特性, 用asm伪指令可以在C程序中包含简短的汇编代码
            • 好处: 减少代码量
            • 坏处: 会使代码与某些特殊的机器有关,所以只应该在想要的特性只能以这种方式才能访问到时才使用它
      • 条件码: 条件码是CPU根据运算结果由硬件设置的位, 体现当前指令执行结果的各种状态信息. 例如: 算术运算产生的正/负/零/溢出等结果.
        • 奇偶标志(parity flag):
          • 定义: 用于反映运算结果中"1"的个数的奇偶性
          • 作用: 为了提供传送的可靠性, 如果采用奇偶校验的方法, 就可使用该标志位
  • 3.3 数据格式
    • 由于是从16位体系结构扩展成32字, Intel用术语"字(word)"表示16位数据类型. 因此32位数为"双字(double words)", 称64位数为"四字(quad words)".
    • 数据格式的汇编后缀:
      • 后缀"l": 表示4字节整数和8字节双精度浮点数, 这样不会产生歧义, 因为浮点数使用的是一组完全不同的指令和寄存器
  • 3.4 访问信息
    • 通用目的寄存器:
      • 作用: 用来存储整数数据和指针
      • 数量: 16
      • 详情:
        • 8位: | %al | %bl | %cl | %dl | %sil | %dil | %bpl | %spl | %r8b | %r9b | %r10b | %r11b | %r12b | %r13b | %r14b | %r15b |
        • 16位: | %ax | %bx | %cx | %dx | %si | %di | %bp | %sp | %r8w | %r9w | %r10w | %r11w | %r12w | %r13w | %r14w | %r15w |
        • 32位: | %eax | %ebx | %ecx | %edx | %esi | %edi | %ebp | %esp | %r8d | %r9d | %r10d | %r11d | %r12d | %r13d | %r14d | %r15d |
        • 64位: | %rax | %rbx | %rcx | %rdx | %rsi | %rdi | %rbp | %rsp | %r8 | %r9 | %r10 | %r11 | %r12 | %r13 | %r14 | %r15 |
          • 不同字节数的操作码可以访问不同的最低寄存器
    • 3.4.1 操作数指示符
      • 操作数: 一个操作中要使用的源数据值, 以及放置结果的目的位置
        • 操作数本身没有数据类型的标志, 它的数据类型由操作码确定
      • 操作数格式:
        • 产生原因: 源数据值可以以常数形式给出, 或是从寄存器或内存中读出. 结果可以存放在寄存器或内存中. 因此, 不同的操作数可以分为三种类型:
          1. 立即数: 用来表示常数值
          2. 寄存器: 表示某个寄存器的内容
          3. 内存引用: 根据计算出来的==地址==(通常是有效地址)访问某个内存位置
    • 3.4.2 数据传送指令
      • 注意点:
        • movabsq: 源操作数只能为64位立即数, 目的操作数只能是寄存器
        • 指令如何修改目的寄存器的高字节数: 按照操作码的不同, 有不同的方式. 有些操作码会保持高位不变, 有些会将高位设置为0, 有些会将高位设置为符号位
        • x86-64的限制: 传送指令的两个操作数不能都指向内存位置
        • movq只能以表示32位的补码数字的立即数作为源操作数, 然后把这个值符号扩展为64位的值, 放到目的寄存器
        • 立即数不能做目的操作数
    • 3.4.4 压入和弹出栈数据
      • 寄存器%rsp:
        • 作用: 栈指针寄存器, 用来存放栈指针的值
  • 3.5 算术和逻辑操作
    • 3.5.1 加载有效地址(load effective address: leaq)
      • 作用: 将一个有效地址写入目的寄存器
        • 有效地址: 计算出来的地址
      • 目的操作数: 必须是寄存器
    • 3.5.2 一元和二元操作
      • 一元操作: 只有一个操作数, 既是源又是目的. 这个操作数可以是一个寄存器或者内存地址
      • 二元操作: 其中第二个操作数既是源又是目的, 第一个操作数可以是立即数/寄存器/内存位置. 第二个操作数是寄存器或内存地址
        • 注意: 当第二个操作数是内存地址时, 处理器必须从内存读出值, 执行操作, 再把结果写回内存
    • 3.5.5 特殊的算术操作
      • imulq:
        • 一般用法:
        imulq   %rdx, %rcx
        
        • 特殊用法:
        imulq   %rdx     //有符号乘法
        mulq   %rdx     //无符号乘法
        
          - 作用: 计算两个64位值的全128位乘积
          - 注意点: 要求一个参数必须在寄存器%rax中, 而另一个作为指令的操作源给出. 然后乘积存放在寄存器%rdx(高64位)和%rax(低64位)中
        
  • 3.6 控制
    • 3.6.1 条件码
      • 常用条件码:
        • CF(Carry Flag): 进位标志
        • ZF(Zero Flag): 零标志
        • SF(Sign Flag): 符号标志
        • OF(Overflow Flag): 溢出标志
      • CMP: cmp系列指令会比较两个操作数并设置条件码,而不改变目的寄存器
      • 条件码的改变:
        • 绝大部分指令的执行都会设置条件码
        • lea系列指令不改变条件码
          • 原因: lea系列是用来进行地址计算的
    • 3.6 2 访问条件码
      • SET: set系列指令可以根据条件码的某种组合, 将一个字节设置为0或1
      • 溢出:
        • 负溢出: 当计算结果本应该是负数但寄存器中却存放的是正数时为负溢出
        • 正溢出: 当计算结果本应该是正数但寄存器中却存放的是负数时为正溢出
        • 详见2.3.2 补码加法
    • 3.6.4 跳转指令的编码
      • 汇编: 将汇编代码转化成机器码
      • 反汇编: 将机器码转化成汇编代码
      • 理解跳转指令目标的如何编码, 对第7章研究链接非常重要
        • 汇编代码中: 跳转目标用符号标号书写
        • 汇编器, 以及后来的链接器, 会产生跳转目标的适当编码
          • 跳转指令有几种编码, 通常使用PC相对寻址(PC-relative)
            • PC-relative: 会将目标指令的地址与紧跟在跳转指令后面的那条指令的地址之间的差作为编码
              • 优点:
                1. 使用PC-relative时, 当使用链接器将这些代码重新定位时, 跳转目标的编码并没有改变
                2. 指令编码很简洁
                3. 目标代码可以不做改变的移动到内存的不同位置
            • "绝对"地址: 用4个字节直接指定目标
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,026评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,655评论 1 296
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,726评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,204评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,558评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,731评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,944评论 2 314
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,698评论 0 203
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,438评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,633评论 2 247
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,125评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,444评论 3 255
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,137评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,103评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,888评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,772评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,669评论 2 271

推荐阅读更多精彩内容