x86 instruction "movb $5, var(,1)"

3
我正在阅读一篇关于AT&T语法下x86汇编的教程,并遇到了这个指令: movb $5, var(,1) — 将值5存储到var位置上的字节中。 var(,1)后面的 (,1)是什么意思?这种后缀的通用语法是什么?

3
在这种情况下,那样做毫无用处。无论如何,那就是 AT&T 有效地址语法,有一些部分被省略了。请参考手册。至少 GNU 汇编程序 v2.28 生成的代码与仅使用var相同。其他版本可能需要发出一个 SIB 字节。 - Jester
1个回答

2
这种说法非常不寻常;我以前从未见过有人这样写,针对没有寄存器的静态标签。
可能是试图指示一个没有基址或索引的 SIB 字节,而不是让汇编器使用只有 ModRM 字节的更短编码。
(是的,这是可能的。32 位寻址模式有两种冗余的方式来编码 [disp32] 绝对地址。x86-64 重新定义了较短的一种作为 RIP 相关寻址。另请参见 rbp not allowed as SIB base?
但是当前的 GAS 忽略它,并将其编码为与 var 相同。
因此,也许这是提醒您这是一个内存操作数的尝试,就像总是在 Intel 语法中使用 [var] 而不是 mov var, al 一样(在类似于 GNU .intel_syntax 的 MASM 风格的 Intel 语法中有效,但不适用于 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所支持的所有三种变体,因此生成的二进制文件完全相同。(至少我正在反汇编的.text节;可能在其他节中有一些差异。)
那么也许使用“cmp $1,(var)”是使内存操作数明确的好方法?但这并不太好,因为与英特尔语法不同,你不能仅仅通过添加寄存器来实现,你必须将“var”移出括号。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接