x86 指令 "movb , var(,1)"
x86 instruction "movb $5, var(,1)"
我正在阅读有关 AT&T 语法的 x86 汇编的tutorial,我遇到了这条指令
movb , var(,1)
— 将值 5 存储到位置 var.
的字节中
var
后面的(,1)
是什么意思?这种后缀的一般语法是什么?
至少可以说这是非常规的风格;我以前从未见过有人这样写,用于寻址没有寄存器的静态标签。
可能会尝试指示 SIB 字节(没有基数或索引),而不是允许汇编器使用仅包含 ModRM 字节的较短编码。
(是的,这是可能的。32 位寻址模式有 2 种冗余方式来编码 [disp32]
绝对地址。x86-64 将较短的一种重新定义为 RIP 相对寻址。另见 )
但是当前的 GAS 会忽略它并将其编码为 var
.
所以这可能是为了提醒你这是一个内存操作数,就像在英特尔语法中总是使用 [var]
而不是 mov var, al
(这在 MASM 风格的英特尔语法中有效,例如 GNU .intel_syntax
,但在 NASM).
中无效
What is the general syntax for such suffix?
或者他们这样做只是为了始终对内存操作数使用 disp(basereg, idxreg, scale)
语法,省略未使用的部分。
测试来源:
var: # this won't be in writeable memory, it will assemble but not run
movb , var
movb , var(,1)
movb , (var) # turns out this is valid, too!
#movb , var(%rip) # RIP-relative is x86-64 only, but it's recommended when available.
# movb , var() # Error: junk `()' after expression
# movb , (var,,1) # also invalid
# movb , (var,%ecx,1) # also invalid.
# movb , (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 , (var)
是使内存操作数显式化的好方法? 但这不是很好,因为与 Intel 语法不同,你不能只 add 注册到那个,你必须将 var
移到括号之外。
我正在阅读有关 AT&T 语法的 x86 汇编的tutorial,我遇到了这条指令
movb , var(,1)
— 将值 5 存储到位置 var.
var
后面的(,1)
是什么意思?这种后缀的一般语法是什么?
至少可以说这是非常规的风格;我以前从未见过有人这样写,用于寻址没有寄存器的静态标签。
可能会尝试指示 SIB 字节(没有基数或索引),而不是允许汇编器使用仅包含 ModRM 字节的较短编码。
(是的,这是可能的。32 位寻址模式有 2 种冗余方式来编码 [disp32]
绝对地址。x86-64 将较短的一种重新定义为 RIP 相对寻址。另见
但是当前的 GAS 会忽略它并将其编码为 var
.
所以这可能是为了提醒你这是一个内存操作数,就像在英特尔语法中总是使用 [var]
而不是 mov var, al
(这在 MASM 风格的英特尔语法中有效,例如 GNU .intel_syntax
,但在 NASM).
What is the general syntax for such suffix?
或者他们这样做只是为了始终对内存操作数使用 disp(basereg, idxreg, scale)
语法,省略未使用的部分。
测试来源:
var: # this won't be in writeable memory, it will assemble but not run
movb , var
movb , var(,1)
movb , (var) # turns out this is valid, too!
#movb , var(%rip) # RIP-relative is x86-64 only, but it's recommended when available.
# movb , var() # Error: junk `()' after expression
# movb , (var,,1) # also invalid
# movb , (var,%ecx,1) # also invalid.
# movb , (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 , (var)
是使内存操作数显式化的好方法? 但这不是很好,因为与 Intel 语法不同,你不能只 add 注册到那个,你必须将 var
移到括号之外。