Assembly 将[symbol+;constant]英特尔语法寻址模式转换为AT&;T语法?

Assembly 将[symbol+;constant]英特尔语法寻址模式转换为AT&;T语法?,assembly,offset,att,addressing-mode,intel-syntax,Assembly,Offset,Att,Addressing Mode,Intel Syntax,我只是不知道如何在移动值时向目标添加偏移量,特别是在英特尔语法中,我有: MOV [gdtr + 2], EAX 对于AT&T语法,我尝试将其转换为: movl %eax, gdtr(2,1) 它在编译表达式后的junk'(2,1)时出错,但只使用gdtr(,1)就可以了 我不明白为什么我不能使用基准偏移量,而只能使用比例因子。简单地写一下 movl %eax, gdtr+2 基址偏移量寻址仅在偏移量为寄存器时有效。使用寻址模式将两个常量相加是没有意义的;其工作方式(无论语法如何)是,

我只是不知道如何在移动值时向目标添加偏移量,特别是在英特尔语法中,我有:

MOV   [gdtr + 2], EAX
对于AT&T语法,我尝试将其转换为:

movl %eax, gdtr(2,1)
它在编译表达式后的
junk'(2,1)时出错,但只使用
gdtr(,1)
就可以了

我不明白为什么我不能使用基准偏移量,而只能使用比例因子。

简单地写一下

movl %eax, gdtr+2

基址偏移量寻址仅在偏移量为寄存器时有效。使用寻址模式将两个常量相加是没有意义的;其工作方式(无论语法如何)是,汇编器/链接器将指令编码的位移字段的
symbol+常量
解析为单个数字。

它只是
gdtr+2

gdtr(2,1)
[给出一个错误],但是只使用
gdtr(,1)
就可以了

AT&T寻址模式下
()
参数中的内容只能是寄存器(和比例因子):
disp(基、索引、比例)
。基址和索引是可选的,因此空是可以的,但无效(非寄存器)不是。

当您指定一个没有基或索引的比例时,显然您只能使用一个逗号:
(,,1)
是一个关于空比例因子的错误。
您可以将它写成
gdtr+2(,1)
来显式地不使用寄存器

在寻址模式下,+2是移位的一部分,而不是基寄存器或索引寄存器,无论语法如何。有关寻址模式的编码方式,请参阅或参阅英特尔或AMD手册。(您正在执行的是
[disp32]
[disp16]
寻址模式,即如何将其编码为机器代码。)

正如Nate指出的,链接器负责将汇编时间文字常量+链接时间常量符号地址转换为机器代码中的最终地址,编码为
disp32
(或
disp16
,表示16位地址大小)。对于x86-64,也可以使用RIP relative
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.
与此asm一起编译:

foo:
        movzbl  gdtr+2, %eax
        ret
gdtr:
        .zero   1024
这是您的寻址模式,作为奖励,AT&T的movzx助记符带有字节源。当然,你可以摆弄字体


编译器是有用的资源;他们知道在编译简单C函数时如何以“正常方式”完成很多事情,并且知道调用约定和类型宽度。和AT&T语法,包括函数指针如果遇到困难,请询问编译器。基本上,编译器无法向您显示的唯一内容是
jmp far
(AT&t
ljmp
)的语法。

您还可以将汇编程序切换到英特尔语法。感谢您的帮助!我不知道你可以在AT&t这样做。是的,我想我可以用英特尔风格重写我的代码,但我在AT&t已经有了很多。谢谢大家:)