`

x86-64 中的寄存器与汇编操作数杂述

阅读更多
        Intel 中常用术语“字(word)”表示 16 位数据类型,因此 32 位数称为“双字(double words)”,64 位数称为“四字(quad words)”。下表中给出了 C 语言基本数据类型对应的 x86-64 表示。

        如图所示,大多数 GCC 生成的汇编代码指令都有一个字符的后缀(本文中都是使用 ATT 而非 Intel 汇编代码格式),表明操作数的大小。例如,数据传送指令有四个变种:movb(传送字节)、movw(传送字)、movl(传送双字)和 movq(传送四字)。后缀“l”用来表示双字,因为 32 位数被看成是“长字(long word)”。注意,虽然汇编代码中的 4 字节整数和 8 字节双精度浮点数都使用了该后缀来表示,但这不会产生歧义,因为浮点数使用的是一组完全不同的指令和寄存器。
        一个 X86-64 的 CPU 包含一组 16 个存储 64 位值的通用目的寄存器,用来存储整数数据和指针。下图中显示了这 16 个寄存器。它们的名字都以“%r”开头,后面则跟以随指令集历史演化而来的不同命名规则的名字。最初的 8086 中有 8 个 16 位的寄存器,对应图中的 %ax 到 %bp。每个寄存器都有特殊的用途。扩展到 IA32 架构时,这些寄存器也扩展成 32 位,标号从 %eax 到 %ebp。扩展到 x86-64 后,原来的 8 个寄存器也随之扩展成 64 位,标号从 %rax 到 %rbp。除此之外,还增加了 8 个新的寄存器,它们的标号是按照新的命名规则制定的:从 %r8 到 %r15。

        指令可以对这 16 个寄存器的低位字节中存放的不同大小的数据进行操作:字节级操作可以访问最低的字节,16 位操作可以访问最低的 2 个字节,32 位操作可以访问最低的 4 个字节,而 64 位操作可以访问整个寄存器。
        当相关指令以寄存器作为目标时,对于生成小于 8 字节结果的指令,对寄存器中剩下的字节的处理有两条规则:生成 1 字节和 2 字节数字的指令会保持剩下的字节不变;生成 4 字节数字的指令会把高位 4 个字节置为 0,这是作为从 IA32 到 x86-64 的扩展的一部分而采用的。
        多数指令都有一个或多个操作数(operand),用于指示一个操作中要使用的源数据值,以及放置结果的目的位置。源数据值可以是常数,或是从寄存器或内存中读出,结果可以存放在寄存器或内存中。因此,各种不同的操作数的可能性被分为三种类型。第一种是立即数(immediate),用来表示常数值。在 ATT 格式的汇编代码中,立即数的书写方式是“$”后面跟一个用标准 C 表示法表示的整数,如 $-577 或 $0x1F。不同的指令允许的立即数值范围不同,汇编器会自动选择最紧凑的方式进行数值编码。第二种是寄存器(register),它表示某个寄存器的内容。第三类是内存引用,它会根据计算出来的地址(通常称为有效地址)访问某个内存位置。x86-64 支持多种不同的寻址模式,允许不同形式的内存引用,如下表所示。

        图中,使用符号 ra 来表示任意寄存器 a,用引用 R[ra] 来表示它的值,这是将寄存器集合看成一个数组 R,用寄存器标识符作为索引。对于内存引用,因为可以将内存看成一个很大的字节数组,所以用符号 Mb[Addr] 表示对存储在内存中从地址 Addr 开始的 b 个字节值的引用(为了简便,通常省略下标 b)。表中底部用语法 Imm(rb, ri, s) 表示的是最常用的形式,它有四个组成部分:一个立即数偏移 Imm,一个基址寄存器 rb,一个变址寄存器 ri 和一个比例因子 s。注意,这里 s 必须是 1、2、4 或者 8,基址和变址寄存器都必须是 64 位寄存器。有效地址被计算为:Imm + R[rb] + R[ri]*s。引用数组元素时,会用到这种通用形式,其他形式都是这种的特殊情况。在引用数组和结构元素时,比较复杂的寻址模式是很有用的。
        下面是一个数据交换函数的 C 语言代码。
long exchange(long *xp, long y){
    long x = *xp;
    *xp = y;
    return x;
}

        其对应的汇编代码主体部分如下。
; long exchange(long *xp, long y)
; xp in %rdi, y in %rsi
exchange:
    movq    (%rdi), %rax         ; Get x at xp. Set as return value.
    movq    %rsi, (%rdi)         ; Store y at xp.
    ret                          ; Return.

        从这段汇编代码中可以看出,C 语言中所谓的“指针”其实就是地址。间接引用指针就是将该指针放在一个寄存器中,然后在内存引用中使用这个寄存器。其次,像 x 这样的局部变量通常是保存在寄存器而不是内存中,因为访问寄存器要比访问内存快得多。

参考书籍:《深入理解计算机系统》第三版第三章——程序的机器级表示。
  • 大小: 99.6 KB
  • 大小: 731.8 KB
  • 大小: 276.7 KB
分享到:
评论

相关推荐

    快速入门汇编语言-非常详细且系统地介绍x86-64汇编语言的文.md

    3. 汇编指令的格式和种类,如操作码、操作数的表示 4. 通过一系列例子详细解释如何阅读和理解汇编代码 5. 重点介绍了函数调用中栈帧的使用 6. 使用很多配图辅助说明 总的来说,这是一篇写得非常好的有关x86_64汇编...

    libftASM:在x86-64程序集中编写一个lib

    libftASM 在x86汇编中编写一个lib(intel风格)X86组装通用寄存器 一些寄存器值在函数调用中保留! 保留的寄存器rbx rsp rbp r12 r13 r14 r15 暂存器rax rdi rsi rdx rcx r8 r9 r10 r11值得注意的指示指令是在运行时...

    C与汇编语言1

    1、x86_64通用寄存器 2、 调用栈 3、导出汇编代码 4、反汇编调试详解 5、结构体反汇编 5、操作数约束 1、x86_64通用寄存器 2、 调用栈 3、

    gcc 中文帮助文档

    x86内联汇编 简述 内联汇编 程序模板 操作数 修饰寄存器列表 操作数约束 示例 寄存器约束 匹配约束 内存操作数约束 修饰寄存器 不同的CPU下最佳编译参数 代码维护 简单cvs automake diff rcs 内核...

    GCC使用教程.pdf

    6. x86 内联汇编 1. 简述 2. 内联汇编 3. 程序模板 4. 操作数 5. 修饰寄存器列表 6. 操作数约束 7. 示例 1. 寄存器约束 2. 匹配约束 3. 内存操作数约束 4. 修饰寄存器 7. 不同的 CPU 下最佳编译参数 8. 代码维护 1. ...

    经典GCC_使用教程

    6. x86内联汇编 1. 简述 2. 内联汇编 3. 程序模板 4. 操作数 5. 修饰寄存器列表 6. 操作数约束 7. 示例 1. 寄存器约束 2. 匹配约束 3. 内存操作数约束 4. 修饰寄存器 7. 不同的CPU下最佳编译参数 8. ...

    The Art of Assembly Language

    本书以X86系列微机为背景,从简单的Hello程序开始,系统而详细地阐述了X86微机汇编语言编程的行种基础知识和编程技巧,内容涉及到数据表示、存储器管理、各种数据类型、过程、与汇编语言相关的体系结构、控制结构、...

    QuadRay-engine:在ARM,MIPS,PPC和x86上使用SIMD的实时raytracer-开源

    QuadRay引擎是一个实时光线跟踪...但大多数实现了32/64位r5 / r6 MSA和POWER 32/64位VMX / VSX(小/大端ISA)(/ w水平减小) / 4-操作数指令计划作为当前2 / 3-操作数SPMD驱动的垂直SIMD ISA的扩展。 请参阅自述文件。

    Windows内核安全与驱动开发光盘源码

    5.2.2 在应用程序中打开与关闭设备 75 5.2.3 设备控制请求 75 5.2.4 内核中的对应处理 77 5.2.5 结合测试的效果 79 5.3 阻塞、等待与安全设计 80 5.3.1 驱动主动通知应用 80 5.3.2 通信接口的测试 81 5.3.3 ...

    Windows内核安全驱动开发(随书光盘)

    5.2.2 在应用程序中打开与关闭设备 75 5.2.3 设备控制请求 75 5.2.4 内核中的对应处理 77 5.2.5 结合测试的效果 79 5.3 阻塞、等待与安全设计 80 5.3.1 驱动主动通知应用 80 5.3.2 通信接口的测试 81 5.3.3 ...

    simple-jit-compiler:该项目旨在说明 JIT 编译器开发中使用的机制

    对于给定的指令,不仅有数百种不同的x86指令,而且可能有数十种不同的机器代码编码(请参阅数字顺序的操作码)。 这里有一些例子: 名称机器码描述添加0x03 ModR/M 将一个32位寄存器添加到另一个。 移动0x8B ModR/M...

    C语言讲义.doc

    1.12.3 SPARC,x86与ARM 18 1.13 汇编语言 18 1.13.1 I386汇编简介 18 1.13.2 VS反汇编 19 1.14 IDE工具 19 1.14.1 QT常用快捷键 19 1.14.2 VS常用快捷键 19 1.14.3 VS断点,调试 19 2 C语言中的数据类型 19 2.1 ...

    uboott移植实验手册及技术文档

    其调用与 CFG_NAND_LEGACY 宏有 关,如果没有定义这个宏,系统调用 drivers/nand/nand.c 中的 nand_init();否则调用自己在 本文件中的 nand_init()函数,本例使用后者。fs2410.c代码如下: #if defined(CONFIG_CMD...

    操作系统(内存管理)

    sbrk 根据参数中给出的字节数移动当前系统中断点,然后返回新的系统中断点。使用参数 0 只是返回当前中断点。这里是我们的 malloc 初始化代码,它将找到当前中断点并初始化我们的变量: 清单 2. 分配程序初始化...

    宋劲彬的嵌入式C语言一站式编程

    2. x86的寄存器 3. 第二个汇编程序 4. 寻址方式 5. ELF文件 5.1. 目标文件 5.2. 可执行文件 19. 汇编与C之间的关系 1. 函数调用 2. main函数和启动例程 3. 变量的存储布局 4. 结构体和联合体 5. C内联汇编 6. ...

    自己动手写操作系统(含源代码).part2

    Woodhull的《操作系统:设计与实现》来学习操作系统的读者,本书尤其适合作为你的引路书籍,因为它翔实地介绍了初学者入门时所必需的知识积累,而这些知识在《操作系统:设计与实现》一书中是没有涉及的,笔者本人...

    Safengine1.8

    将您的关键代码(x86汇编形式)转换成一个新的随机指令集,只有在嵌入您程序中的虚拟机解释器才能运行。这些虚拟机代码是随机生成的,并且经过高度混淆,确保唯一性。 在虚拟化过程中,您原始代码的执行流程将被...

    自己动手写操作系统(含源代码).part1

    Woodhull的《操作系统:设计与实现》来学习操作系统的读者,本书尤其适合作为你的引路书籍,因为它翔实地介绍了初学者入门时所必需的知识积累,而这些知识在《操作系统:设计与实现》一书中是没有涉及的,笔者本人...

    内存管理内存管理内存管理

    如前所述,被映射的内存的边界(最后一个有效地址)常被称为系统中断点或者当前中断点。在很多 UNIX? 系统中,为了指出当前系统中断点,必须使用 sbrk(0) 函数。sbrk 根据参数中给出的字节数移动当前系统中断点,...

    Linux c编程一站式学习

    8.1. 数组的基本操作............................................84 8.2. 数组应用实例:统计随机数..................................86 8.3. 数组应用实例:直方图......................................89 ...

Global site tag (gtag.js) - Google Analytics