AT&T语法

本文主要介绍AT&T汇编语法,适用于有汇编基础且熟悉Intel或NASM语法者。阐述了其在GNU汇编器中的应用,对比了与Intel语法在操作数规范上的差异,还介绍了寄存器、字面量值、内存寻址、操作数大小及控制转移指令等方面的特点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

AT&T语法(一)

For the first timer the AT&T syntax may seem a bit confusing, atleast I felt so. Personally Im a big fan of this syntax and if you ask me it has got its own advantages. It is the syntax understood by the GNU assembler (GAS) and youll have to use this syntax if you inline assembly into C source files which need to be compiled using the GNU C compilers. As far as os development is concerned, for those who work with the GNU Compiler Collection, I blv that a basic knowledge of this syntax is a must. This article is meant only for those who have a basic knowledge of assembly language and preferably some familiarity with the intel and/or NASM assembler syntax.

The AT&T or GAS Assembly Syntax

Like any other assembler, the basic structure of an instruction in GAS is the same. But the difference from the intel syntax starts from the specification of operands for an instruction. For example in the intel syntax, the structure of a data moving instruction is..

 		instruction destination, source

but in the case of GAS, the strucuture is

 		instruction source, destination

which to me makes more sense.

REGISTERS

All register names of the i386+ architecture have to be prefixed by a % sign. Example, %al,%bx, %ds, %cr0 etc. No matter where you use them they must be prefixed by %. For example...

 		mov	%ax,	%bx

which moves the value from register ax to register bx.

LITERAL VALUES

All literal values must be prefixed by a $ sign. For example..

 		mov	$100,	%bx
 		mov	$A,	%al

The first instruction moves the the value 100 into the register ax and the second one movesthe numerical value of the ascii A into the al register. Please note that the below instruction is not valid..

 		mov	%bx,	$100

as it just tries to move the value in register bx to a literal value.

MEMORY ADDRESSING

In GAS, memory is addressed in the following way..

 		
	segment-override:signed-offset(base,index,scale)

For example the GAS equivalent of [es:eax+ebx*2+100] is

		%es:100(%eax,%ebx,2)

Please note that that offsets and the scale should not be prefixed by $. Few more examples with their equivalent NASM syntax..

GAS memory operand			NASM memory operand
------------------			-------------------

100					[100]
%es:100					[es:100]
(%eax)					[eax]
(%eax,%ebx)				[eax+ebx]
(%ecx,%ebx,2)				[ecx+ebx*2]
(,%ebx,2)				[ebx*2]
-10(%eax)				[eax-10]
%ds:-10(%ebp)				[ds:ebp-10]
Example instructions..
 		mov	%ax,	100
 		mov	%eax,	-100(%eax)

The first instruction moves the value in register ax into offset 100 of the data segment register, and the second one moves the value in eax register to [eax-100].

OPERAND SIZES

At times, especially when moving literal values to memory, it becomes neccessary to specify the size of transfer or the operand size. For example the instruction...

 		mov	$10,	100

only specfies that the value 10 to be moved to the memory offset 100, but not the transfer size. In NASM this is done by adding the casting keyword byte/word/dword etc. to any of the operands. In GAS this is done by adding the suffix b/w/l to the instruction. For example ...

 		movb	$10,	%es:(%eax)
moves a byte value 10 to the memory location [ea:eax], whereas..
 		movl	$10,	%es:(%eax)

moves a long value 10 to the same.

A few more examples..

 		movl	$100,	%ebx
 		pushl	%eax
 		popw	%ax

CONTROL TRANSFER INSTRUCTIONS

The jump, call and ret instructions can transfer the control from one part of the code to another. The immediate value jump and call are two operand instructions of the form..

 		jmp	$segment,	$offset
As for absolute jumps, the memory operand should be prefixed by a *.For example..
GAS syntax			NASM syntax
----------			-----------

IMMEDIATE

jmp	$100, $100		jmp  100:100
ljmp	$100, $100		jmp  100:100
call	$100, $100		call 100:100
lcall	$100, $100		call 100:100

ABSOLUTE

jmp	100			jmp  100
call	100			call 100

INDIRECT

jmp	*100			jmp  near [100]
call	*100			call near [100]
jmp	*(%eax)			jmp  near [eax]
call	*(%ebx)			call near [ebx]
ljmp	*100			jmp  far  [100]
lcall	*100			call far  [100]
ljmp	*(%eax)			jmp  far  [eax]
lcall	*(%ebx)			call far  [ebx]

RETURN

ret				retn
lret				retf
lret $0x100			retf 0x100
Thats it for now.
### Intel 语法与 AT&T 语法的区别 在汇编语言中,Intel 语法和 AT&T 语法是两种常见的表示方式,二者的主要区别体现在以下几个方面: --- #### 1. **操作数顺序** - 在 Intel 语法中,指令的操作数顺序是从目标到源,即 `insn destination, source`[^2]。 - 在 AT&T 语法中,操作数顺序则是从源到目标,即 `insn source, destination`。 例如: ```asm // Intel 语法 mov eax, 1 ; 将值 1 移动到寄存器 eax 中 // AT&T 语法 movl $1, %eax ; 将值 1 移动到寄存器 eax 中 ``` --- #### 2. **立即数标记** - 在 Intel 语法中,立即数不需要特殊的前缀或后缀来区分其性质。 - 在 AT&T 语法中,立即数需要用 `$` 符号作为前缀[^3]。 例如: ```asm // Intel 语法 add eax, 4 ; 将寄存器 eax 的值加上 4 // AT&T 语法 addl $4, %eax ; 将寄存器 eax 的值加上 4 ``` --- #### 3. **寄存器命名** - 在 Intel 语法中,寄存器名称前面没有任何修饰符。 - 在 AT&T 语法中,寄存器名称需要以 `%` 开头[^3]。 例如: ```asm // Intel 语法 push ebx ; 将寄存器 ebx 的值压入栈中 // AT&T 语法 pushl %ebx ; 将寄存器 ebx 的值压入栈中 ``` --- #### 4. **内存寻址** - 在 Intel 语法中,内存地址使用方括号 `[]` 表示。 - 在 AT&T 语法中,内存地址使用圆括号 `()` 表示。 例如: ```asm // Intel 语法 mov eax, [ebx+4] ; 将 ebx+4 地址处的内容加载到 eax 寄存器中 // AT&T 语法 movl (%ebx, 4), %eax; 将 ebx+4 地址处的内容加载到 eax 寄存器中 ``` --- #### 5. **指令长度指示符** - 在 Intel 语法中,默认情况下可以根据上下文推断出数据大小(字节、字或双字),无需额外标注。 - 在 AT&T 语法中,通常会在助记符后面附加一个字母来指明操作数的大小:`b` 表示字节(byte),`w` 表示字(word),`l` 表示双字(long)[^3]。 例如: ```asm // Intel 语法 mov eax, dword ptr [ebx] // AT&T 语法 movl (%ebx), %eax ``` --- #### 6. **工具链支持** - Linux 平台上的 GCC 编译器默认采用 AT&T 语法[^4]。 - Windows 平台上常用的 Microsoft Visual Studio 和 NASM 默认采用 Intel 语法。 这种差异使得跨平台开发时需要注意选择合适的汇编风格。 --- ### 总结 Intel 语法和 AT&T 语法之间的主要区别在于操作数顺序、立即数标记、寄存器命名、内存寻址以及指令长度指示符等方面。理解这些差异有助于开发者在不同平台上高效编写和调试汇编代码。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值