AT&T汇编语言与GCC内嵌汇编简介 1 AT&T 与INTEL的汇编语言语法的区别 1.1大小写 1.2操作数赋值方向 1.3前缀 1.4间接寻址语法 1.5后缀 1.6指令 2 GCC内嵌汇编 2.1简介 2.2内嵌汇编举例 2.3语法 2.3.1汇编语句模板 2.3.2输出部分 2.3.3输入部分 2.3.4限制字符 2.3.5破坏描述部分 2.4GCC如何编译内嵌汇编代码 ### AT&T汇编语言与GCC内嵌汇编简介 #### 1. AT&T 与 INTEL 的汇编语言语法的区别 ##### 1.1 大小写 在 INTEL 格式的汇编语言中,指令通常使用大写字母书写,如 `MOV AX, EBX`。而在 AT&T 格式的汇编语言中,则使用小写字母,如 `movl %ebx, %eax`。 ##### 1.2 操作数赋值方向 在 INTEL 汇编语法中,第一个操作数代表目标操作数,第二个操作数代表源操作数,赋值的方向是从右向左。例如: ``` MOV AX, EBX ``` 而在 AT&T 汇编语法中,赋值方向正好相反,即从左向右,更符合人们的直觉理解。例如: ``` movl %ebx, %eax ``` ##### 1.3 前缀 INTEL 汇编语言中的寄存器和立即数不使用任何前缀。而在 AT&T 汇编语言中,寄存器前面需要加上“%”前缀,立即数则需要加上“$”前缀。例如: ``` INTEL: MOV AX, 1 AT&T: movl $1, %eax ``` 对于符号常量,AT&T 汇编语言中可以直接引用,无需添加前缀。但是,如果需要引用符号地址,则应在符号前添加“$”前缀。例如: ``` movl value, %ebx // 直接引用符号常量 value movl $value, %ebx // 引用 value 的地址 ``` ##### 1.4 间接寻址语法 INTEL 汇编语言中,间接寻址使用方括号 `[]`,而在 AT&T 汇编语言中则使用圆括号 `()`。此外,两者处理复杂操作数的方式也有所不同。INTEL 的格式为 `[base + index * scale + disp]`,而 AT&T 的格式为 `%segreg: disp(base, index, scale)`,其中 `%segreg`、`index`、`scale` 和 `disp` 都是可选的。例如: ``` INTEL: Instr foo, [base + index * scale + disp] AT&T: instr %segreg: disp(base, index, scale), foo ``` ##### 1.5 后缀 在 AT&T 汇编语法中,大多数指令操作码的最后一个字母表示操作数的大小:“b”表示字节 (1 字节)、“w”表示字 (2 字节)、“l”表示长字 (4 字节)。例如: ``` INTEL: MOVAL, BL MOVAX, BX MOVEAX, DWORDPTR[EBX] AT&T: movb %bl, %al movw %bx, %ax movl (%ebx), %eax ``` AT&T 汇编语言还支持操作数扩展指令,包括符号扩展指令 `movs` 和零扩展指令 `movz`。例如: ``` movsbl %al, %edx // 字节到长字的符号扩展 ``` ##### 1.6 指令 尽管 INTEL 汇编与 AT&T 汇编的基本指令相似,但它们在语法上有明显的区别。具体的指令语法可以参考 I386 Manual。 #### 2. GCC 内嵌汇编 ##### 2.1 简介 GCC 提供了内嵌汇编功能,可以在 C 代码中直接嵌入汇编指令。这种功能主要用于编写性能敏感或特定架构相关的代码。内嵌汇编使得程序员能够在保持 C 代码的可读性和可移植性的同时,实现底层优化。 ##### 2.2 内嵌汇编举例 以下是一个简单的示例,展示如何在 C 代码中使用内嵌汇编: ```c void swap(int *a, int *b) { asm("xchg %1, %0" : "+r" (*a), "+r" (*b)); } ``` 在这个例子中,`swap` 函数使用了内嵌汇编来交换两个整数变量的值。 ##### 2.3 语法 内嵌汇编的主要组成部分包括: ###### 2.3.1 汇编语句模板 内嵌汇编指令的基本格式为: ``` asm("模板" : 输出描述符 : 输入描述符 : 破坏描述符); ``` 这里的 `"模板"` 是实际的汇编指令字符串,而输出描述符、输入描述符和破坏描述符用于指定指令的输入和输出操作数以及可能被指令修改的寄存器。 ###### 2.3.2 输出部分 输出描述符指定汇编指令的结果,并且与 C 代码中的变量相关联。输出描述符通常使用冒号分隔,并且每个描述符都包含一个约束符和一个对应的 C 表达式。约束符定义了如何解释对应的 C 表达式,例如 `"+r"` 表示该表达式可以作为读写寄存器。 例如: ```c asm("addl %1, %0" : "=r" (result) : "r" (value)); ``` 在这个例子中,`result` 的值将会被更新。 ###### 2.3.3 输入部分 输入描述符定义了汇编指令所需的输入,并与 C 代码中的变量相关联。输入描述符同样使用冒号分隔,并且每个描述符都包含一个约束符和一个对应的 C 表达式。 例如: ```c asm("addl %1, %0" : "=r" (result) : "r" (value)); ``` 在这里,`value` 的值将被作为输入。 ###### 2.3.4 限制字符 限制字符用于描述汇编指令的输入输出操作数。这些字符定义了操作数的类型,例如 `"r"` 表示任何寄存器都可以接受,`"m"` 表示内存位置等。 例如: ```c asm("movl %0, %1" : "=m" (mem) : "r" (reg)); ``` 在这个例子中,`reg` 的值将被移动到由 `mem` 指定的内存位置。 ###### 2.3.5 破坏描述部分 破坏描述符用来指定那些可能会被汇编指令修改的寄存器。这是为了确保 GCC 在编译时不会依赖于这些寄存器的值。破坏描述符通常出现在最后一个冒号之后。 例如: ```c asm("addl %1, %0" : "=r" (result) : "r" (value) : "cc"); ``` 在这个例子中,`cc` 表示条件码寄存器可能会被修改。 ##### 2.4 GCC 如何编译内嵌汇编代码 GCC 在编译内嵌汇编代码时会遵循一定的规则。它会解析汇编指令模板中的指令,并确定所需的输入和输出操作数。接下来,GCC 会根据输入和输出描述符以及可能的破坏描述符调整其内部寄存器分配策略,确保代码正确地生成。 AT&T 汇编语言与 INTEL 汇编语言在语法上有显著的不同之处,这些差异主要体现在大小写、操作数赋值方向、前缀、间接寻址语法等方面。GCC 内嵌汇编功能提供了一种灵活的方法,使程序员能够在 C 代码中直接使用底层汇编指令,这对于优化性能和编写特定架构的代码非常有用。
剩余16页未读,继续阅读
- 粉丝: 0
- 资源: 4
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- TatSu-4.4.0-cp38-cp38-win_amd64.whl.rar
- TatSu-4.4.0-cp37-cp37m-win_amd64.whl.rar
- TatSu-5.6.0-py3-none-any.whl.rar
- TatSu-4.4.0-cp38-cp38-win32.whl.rar
- 42-在线图书管理.zip
- tensorflow-1.9.0-cp36-cp36m-win_amd64.whl.rar
- texture2ddecoder-1.0.4-cp37-cp37m-win_amd64.whl.rar
- texture2ddecoder-1.0.4-cp37-cp37m-win32.whl.rar
- 237-springboot就业系统.zip
- tensorflow-1.9.0-cp37-cp37m-win_amd64.whl.rar
- texture2ddecoder-1.0.4-cp38-cp38-win32.whl.rar
- texture2ddecoder-1.0.4-cp38-cp38-win_amd64.whl.rar
- texture2ddecoder-1.0.4-cp39-cp39-win_amd64.whl.rar
- texture2ddecoder-1.0.4-cp39-cp39-win32.whl.rar
- texture2ddecoder-1.0.4-cp310-cp310-win_amd64.whl.rar
- texture2ddecoder-1.0.4-cp310-cp310-win32.whl.rar