我正在阅读有关AT&T语法的tutorial x86汇编程序,并且遇到了此说明
movb $5, var(,1)
—将值5存储到位置var的字节中。
(,1)
之后的var
表示什么?这种后缀的一般语法是什么?
答案 0 :(得分:3)
至少可以说这是非常规风格;我以前从未见过有人写过这样的东西来写没有寄存器的静态标签。
这可能是试图指示一个SIB字节(没有基数或索引),而不是允许汇编器使用仅带有ModRM字节的较短编码。
(是的,这是可能的。32位寻址模式具有2种冗余方式来编码[disp32]
绝对地址。x86-64将较短的一种重新定义为RIP相对寻址。另请参见rbp not allowed as SIB base?)< / p>
但是当前的GAS会忽略它,并将其编码与var
相同。
因此,可能是想提醒您这是一个内存操作数,就像始终在Intel语法中使用[var]
而不是mov var, al
(在MASM中有效)样式的Intel语法,例如GNU .intel_syntax
,但不是NASM)。
这种后缀的一般语法是什么?
也许他们只是为了保持一致性,始终对内存操作数使用 disp(basereg, idxreg, scale)
语法,而忽略了未使用的部分。
测试源:
var: # this won't be in writeable memory, it will assemble but not run
movb $5, var
movb $5, var(,1)
movb $5, (var) # turns out this is valid, too!
#movb $5, var(%rip) # RIP-relative is x86-64 only, but it's recommended when available.
# movb $5, var() # Error: junk `()' after expression
# movb $5, (var,,1) # also invalid
# movb $5, (var,%ecx,1) # also invalid.
# movb $5, (var+%eax,%ecx,1) # also invalid.
as --version
在我的系统上打印GNU assembler (GNU Binutils) 2.31.1
。
$ gcc -m32 -no-pie -nostdlib foo.s
/usr/bin/ld: warning: cannot find entry symbol _start; defaulting to 0000000008049000
# I just wanted a linked binary with real addresses filled in, not to run it.
# entry = start of the .text section is fine.
$ objdump -drwC -Mintel a.out
08049000 <var>:
8049000: c6 05 00 90 04 08 05 mov BYTE PTR ds:0x8049000,0x5
8049007: c6 05 00 90 04 08 05 mov BYTE PTR ds:0x8049000,0x5
804900e: c6 05 00 90 04 08 05 mov BYTE PTR ds:0x8049000,0x5
Clang 7.0的内置汇编器还接受GAS所做的所有3个变体,从而形成相同的二进制文件。 (至少我正在拆卸的.text
部分;可能在另一部分的某些地方有所不同。)
那么也许cmp $1, (var)
是使内存操作数显式的好方法?但这不是很好,因为与Intel语法不同,您不能只是 add 对此进行注册,则必须将var
移到括号之外。