[英]Converting [symbol + constant] Intel syntax addressing mode to AT&T syntax?
我只是无法弄清楚如何在移动值时向目标添加偏移量,特别是在我拥有的英特尔语法中:
MOV [gdtr + 2], EAX
对于 AT&T 语法,我尝试将其转换为:
movl %eax, gdtr(2,1)
junk '(2,1)' after expression
时会出错,但仅使用gdtr(,1)
可以正常工作。
我不明白为什么我不能使用基本偏移,而只能使用比例因子。
简单地写
movl %eax, gdtr+2
基偏移寻址仅在偏移为寄存器时才有效。 使用寻址模式将两个常量相加是没有意义的。 其工作方式(无论语法如何)是汇编程序/linker 将symbol+constant
解析为指令编码的位移字段的单个数字。
就是gdtr+2
gdtr(2,1)
[给出错误] 但仅使用gdtr(,1)
工作正常。
AT&T 寻址模式中()
括号内的内容只能是寄存器(和比例因子): disp(base, index, scale)
。 基数和索引是可选的,所以空是可以的,但无效(非注册)不是。
当您指定一个没有基数或索引的比例时,显然您必须只使用一个逗号: (,,1)
是关于空比例因子的错误。
您可以将其写为gdtr+2(,1)
以显式不使用寄存器。
+2 是寻址模式中位移的一部分,而不是基址或索引寄存器,无论语法如何。 请参阅有关 [base + index*scale + disp] 或 Intel 或 AMD 的有关寻址模式如何编码的手册的几个问题。 (就如何将其编码为机器代码而言,您正在做的是[disp32]
或[disp16]
寻址模式。)
正如 Nate 所指出的,linker 负责将汇编时文字常量 + 链接时常量符号地址转换为机器代码中的最终地址,编码为disp32
(或disp16
用于 16 位地址大小)。 或用于 x86-64 的 RIP 相对rel32
。
有趣的事实:一些 AT&T 汇编器接受(gdtr)
作为gdtr
的替代品,但不接受2(gdtr)
。
通常,如果您卡在 NASM -> AT&T 上,您可以组装 NASM 源代码(例如nasm -felf
)并使用 AT&T 反汇编程序(如objdump -drwC
)进行反汇编。 但这对符号寻址模式语法没有帮助,因为充其量objdump -dr
只是用符号名称信息注释数字寻址模式。
因此,在这种情况下,您最好的选择是让 GCC 或 clang 发出使用符号名称和数字常量的指令,如下所示
char gdtr[1024]; // global var so it has a symbol
char foo() { return gdtr[2]; } // load from global symbol + constant.
在 Godbolt 编译器资源管理器上使用gcc9.3 -O2 -m32
编译到这个 asm:
foo:
movzbl gdtr+2, %eax
ret
gdtr:
.zero 1024
有你的寻址模式,作为奖励,带有字节源的 movzx 的 AT&T 助记符。 当然,您可以摆弄类型。
编译器是有用的资源; 在编译简单的 C 函数时,他们知道如何以“正常方式”做很多事情,并且他们知道调用约定和类型宽度。 包括 function 指针在内的所有内容的 AT&T 语法。 如果您遇到困难,请询问编译器。 基本上,您唯一无法让编译器向您展示的是jmp far
的语法(AT&T ljmp
)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.