繁体   English   中英

将 [symbol + constant] Intel 语法寻址模式转换为 AT&T 语法?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM