`

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
分享到:
评论

相关推荐

    86系列汇编指令与机器码对照表_×86-64机器指令_x86_furnitureybl_汇编_

    而汇编操作数则是这些指令所操作的数据,可以是寄存器、内存地址或者立即数。 64位的x86-64架构,也称为AMD64或EM64T,是在原有的32位x86基础上扩展的,引入了新的寄存器和寻址模式,允许更大的地址空间和更高效的...

    电子书《x86-64 Assembly Language Programming with Ubuntu 》

    书中可能包含以下章节内容:介绍汇编语言的基本概念、x86-64指令集、Ubuntu环境下的开发工具(如GCC、GDB)、内存模型、程序结构、输入/输出操作、中断处理、异常和错误处理,以及如何将汇编代码与高级语言混合编程...

    x86-64 下函数调用及栈帧原理 - 知乎1

    总结起来,x86-64下的函数调用和栈帧原理涉及了寄存器的管理、堆栈操作和控制流的转移,这些都是为了确保函数调用的正确性和效率。这些概念对于理解底层计算机系统的工作原理以及编写高效的汇编代码至关重要。

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

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

    ASM-Experiments:x86-64 Intel汇编器实用程序例程和程序

    《x86-64 Intel汇编器实用程序例程和程序》是一个深入探讨汇编语言编程的资源集合,特别关注于Intel架构的x86-64指令集。汇编语言是计算机科学中的基本编程语言,它直接对应于机器码,对底层硬件操作有直接控制力,...

    x86-64-gdb常用指令(英文)

    本文将介绍在x86-64系统中使用gdb的常用指令,包括程序的启动与停止、设置断点、执行控制、查看代码、查看数据以及操作内存等。 首先,要启动gdb调试器,通常输入"gdb"命令即可。如果需要调试的程序文件已知,可以...

    [原创]x86指令解析-legacy

    内存/寄存器操作数字节(ModR/M)和索引寻址描述字节(SIB)用于确定操作数的位置和操作类型。ModR/M字节由Mod、Reg/Opcode和R/M三部分组成。Mod字段指示寻址模式,R/M字段用于选择特定的寄存器或者指定内存寻址的...

    x86汇编指令集大全(带注释).pdf

    X86汇编指令集是计算机体系结构中不可或缺的一部分,特别是在32位和64位的x86架构处理器中。这篇文档详细列举了汇编指令,并为每条指令提供了注释说明。以下知识点涵盖了文档中提及的关键指令及其功能。 一、数据...

    汇编语言--x86汇编指令集大全.zip

    **汇编语言与x86汇编指令集详解** 汇编语言是一种低级编程语言,它是计算机硬件系统可以直接理解和执行的指令集的符号化表示。在个人计算机领域,x86架构是主流,对应的汇编语言就是x86汇编语言。这种语言直接对应...

    一些ICS的笔记1

    【ICS笔记1】这篇笔记主要涉及的是x86-64架构下...综上所述,这篇笔记提供了关于x86-64汇编语言和C语言在数据处理、指令格式、寄存器使用、类型转换以及栈操作的基础知识,这对于理解和编写x86-64平台的程序至关重要。

    Programming Assignment 6.pdf

    在本编程作业中,你将学习如何在编译器中实现代码生成,特别是针对简化语言(SimpliC)的x86-64汇编代码生成。x86-64是64位x86架构的别名,也称为AMD64或EM64T。为了完成这项任务,你需要一个Linux环境,可以通过SSH...

    x86,x64 汇编代码注入器 C,C++写的

    《x86,x64汇编代码注入器的C/C++实现详解》 在计算机编程领域,代码注入是一种技术,它允许程序将代码插入到另一个正在运行的进程上下文中执行。这种技术通常用于调试、系统监控、性能优化,但也可能被滥用进行恶意...

    x86_64汇编调试程序初步

    寄存器用于存储操作数、中间结果和地址,是汇编语言编程中非常重要的资源。以下是一些关键寄存器的功能说明: - rdi(寄存器):用来存储函数的第一个参数。 - rsi:用来存储函数的第二个参数。 - rdx:用来存储...

    Linux中x86的内联汇编

    - **修饰寄存器列表**:可以使用不同的修饰符来进一步限定寄存器的使用方式,例如`=r`表示操作数将被分配到寄存器中,并且是输出操作数。 - **操作数约束**:定义了操作数可以出现在指令中的哪些位置。例如,`"r"`...

    x86寄存器详解-杨添宝1

    以下是关于x86寄存器的详细解释: 一、通用寄存器 通用寄存器是处理器中最常用的一类寄存器,它们在32位x86体系中扩展了16位8086的寄存器,提供了8位、16位和32位的操作。主要分为数据寄存器、变址寄存器和地址指针...

    x86x64体系探索及编程

    1. **x86与x64架构**:x86是指英特尔的32位微处理器系列,包括80386、Pentium等。而x64(也称为AMD64或EM64T)是x86架构的64位扩展,最初由AMD推出,后来被Intel广泛采用。x64架构不仅支持传统的32位应用程序,还能...

    -----汇编语言原理与应用-----

    4. 操作码与操作数:操作码表示要执行的操作,操作数则是操作的对象。 5. 转移指令:如JMP、CALL等,用于改变程序的执行流程。 6. 子程序和堆栈:通过调用子程序和使用堆栈,可以实现复杂的逻辑控制和数据管理。 7. ...

    汇编基础有关寄存器和数据传送指令

    2. **传送-填充指令**:MOVSX和MOVZX,用于将位数较短的源操作数扩展到位数较长的目的操作数,MOVSX根据源操作数符号位填充,而MOVZX用0填充。 3. **交换指令XCHG**:交换两个寄存器或寄存器与内存位置的内容。 4....

    将AX寄存器中的16位数分成4组,每组4位,然后把这四组数分别放在AL、BL、CL和DL中。

    在计算机编程,特别是汇编语言中,我们经常需要对数据进行操作,包括拆分和重组。这个场景描述了一个具体的操作,即将AX寄存器中的16位数值分成四部分,每部分4位,然后分别存储到AL、BL、CL和DL这四个8位寄存器中。...

Global site tag (gtag.js) - Google Analytics