如何使用地址常量GCC x86的内联汇编 [英] How to use address constants in GCC x86 inline assembly

查看:177
本文介绍了如何使用地址常量GCC x86的内联汇编的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

GCC的工具链使用AT&放大器;通过缺省值T汇编语法,但对于Intel语法的支持是通过 .intel_syntax 指令提供

The GCC toolchain uses AT&T assembler syntax by default, but support for Intel syntax is available via the .intel_syntax directive.

此外,无论是AT& T公司和Intel的语法是在 preFIX 没有preFIX 的版本,这在他们是否不要求与印记preFIX寄存器名称不同。

Additionally, both AT&T and Intel syntax are available in a prefix and a noprefix version, which differ in whether or not they require to prefix register names with a % sigil.

根据该指令是present,对于地址格式常数的变化。

Depending on which directives are present, the format for address constants changes.

让我们考虑下面的C code

Let's consider the following C code

*(int *)0xdeadbeef = 0x1234;

使用 objdump的-d ,我们发现它的编译下面的汇编指令

Using objdump -d, we find that it's compiled to the following assembler instruction

movl $0x1234,0xdeadbeef

由于没有涉及到寄存器,这对于正确的语法 .att_syntax preFIX .att_syntax没有preFIX ,即得。嵌入C code,它们看起来像这样

As there are no registers involved, this is the correct syntax for both .att_syntax prefix and .att_syntax noprefix, ie. embedded in C code, they look like this

__asm__(".att_syntax prefix");
__asm__("movl $0x1234,0xdeadbeef");

__asm__(".att_syntax noprefix");
__asm__("movl $0x1234,0xdeadbeef");

您可以选择环绕地址常量与括号,即

You can optionally surround the address constant with parentheses, ie.

__asm__("movl $0x1234,(0xdeadbeef)");

将正常工作。

在添加印记,以一个普通地址不变,code将无法完成copile

When adding a sigil to a plain address constant, the code will fail to copile

__asm__("movl $0x1234,$0xdeadbeef"); // won't compile

在围绕这个前pression与paranthesis,编译器会发出错误的code没有警告,即

When surrounding this expression with paranthesis, the compiler will emit wrong code without warning, ie

__asm__("movl $0x1234,($0xdeadbeef)"); // doesn't warn, but doesn't work!

这将发出错误指令

movl $0x1234,0x0

在英特尔模式下,地址常量必须与段寄存器以及操作数的大小和是否歧义是尽可能 PTR 标志pfixed $ P $。在我的机器(英特尔双核笔记本电脑与Windows XP和当前的MinGW和Cygwin版本的GCC),寄存器 DS 默认情况下使用。

In Intel mode, an address constant has to be prefixed with a segment register as well as the operand size and the PTR flag if ambiguity is possible. On my machine (an Intel dual core laptop with Windows XP and current MinGW and Cygwin GCC versions), the register ds is used by default.

方括号是可选的。地址常量也正确识别如果省略段寄存器,但是肘present。省略寄存器发出我的系统上警告,虽然。

Square brackets around the constant are optional. The address constant is also correctly recognized if the segment register is omitted, but the brackets are present. Omitting the register emits a warning on my system, though.

preFIX 模式下,段寄存器是prefixed与,但只能用括号仍然可以工作。这些都是不同的方法来产生正确的指令:

In prefix mode, the segment register has to be prefixed with %, but only using brackets will still work. These are the different ways to generate the correct instruction:

__asm__(".intel_syntax noprefix");
__asm__("mov DWORD PTR ds:0xdeadbeef,0x1234");
__asm__("mov DWORD PTR ds:[0xdeadbeef],0x1234");
__asm__("mov DWORD PTR [0xdeadbeef],0x1234"); // works, but warns!

__asm__(".intel_syntax prefix");
__asm__("mov DWORD PTR %ds:0xdeadbeef,0x1234");
__asm__("mov DWORD PTR %ds:[0xdeadbeef],0x1234");
__asm__("mov DWORD PTR [0xdeadbeef],0x1234"); // works, but warns!

都省略段寄存器和支架将无法编译

Omitting both segment register and brackets will fail to compile

__asm__("mov DWORD PTR 0xdeadbeef,0x1234"); // won't compile

我要纪念这个问题进行的社区维基的,所以如果你有任何有用的补充,随意这样做的。

I'll mark this question as community wiki, so if you have anything useful to add, feel free to do so.

推荐答案

没有preFIX / preFIX 指令只控制寄存器是否需要 preFIX(*)(至少看起来如此,这就是文档中提到的唯一区别)。值的文字总是需要一个 $ $ P $在AT&放PFIX; T语法和从未在Intel语法。所以下面的工作:

The noprefix/prefix directives only control whether registers require a % prefix(*) (at least it seems so and that's the only difference the documentation mentions). Value literals always need a $ prefix in AT&T syntax and never in Intel syntax. So the following works:

__asm__(".intel_syntax prefix");
__asm__("MOV [DWORD PTR 0xDEADBEEF], 0x1234");

如果你真的倾向于到C code编译GCC和GAS组装中使用Intel语法内联汇编,不要忘了还添加以下后,使汇编程序可以神交的其余部分( AT& T公司语法)装配通过GCC生成的:

If you are really inclined to use Intel syntax inline assembly within C code compiled with GCC and assembled with GAS, do not forget to also add the following after it, so that the assembler can grok the rest of the (AT&T syntax) assembly generated by GCC:

__asm__(".att_syntax prefix");

我看到了preFIX的理由/没有preFIX区别是,对于AT& T公司语法中, preFIX不真正需要的基于英特尔架构寄存器,因为寄存器被命名。但是,对于均匀性也可以是有,因为一些其他架构(即SPARC)有编号登记,在这种情况下,单独指定一个低的数字将是不明确的,是否一个内存地址或寄存器中的意思。

The reasoning I see for the prefix/noprefix distinction is, that for AT&T syntax, the % prefix is not really needed for registers on Intel architecture, because registers are named. But for uniformity it can be there because some other architectures (i.e. SPARC) have numbered registered, in which case specifying a low number alone would be ambiguous as to whether a memory address or register was meant.

这篇关于如何使用地址常量GCC x86的内联汇编的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆