x86指令“ movb $ 5,var(,1)”

时间:2019-02-03 23:01:13

标签: assembly x86 att

我正在阅读有关AT&T语法的tutorial x86汇编程序,并且遇到了此说明

movb $5, var(,1) —将值5存储到位置var的字节中。

(,1)之后的var表示什么?这种后缀的一般语法是什么?

1 个答案:

答案 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移到括号之外。