Note that there are some explanatory texts on larger screens.

plurals
  1. POHow to use address constants in GCC x86 inline assembly
    primarykey
    data
    text
    <p>The GCC toolchain uses AT&amp;T assembler syntax by default, but support for Intel syntax is available via the <code>.intel_syntax</code> directive.</p> <p>Additionally, both AT&amp;T and Intel syntax are available in a <code>prefix</code> and a <code>noprefix</code> version, which differ in whether or not they require to prefix register names with a <code>%</code> sigil.</p> <p>Depending on which directives are present, the format for address constants changes.</p> <p>Let's consider the following C code</p> <pre><code>*(int *)0xdeadbeef = 0x1234; </code></pre> <p>Using <code>objdump -d</code>, we find that it's compiled to the following assembler instruction</p> <pre><code>movl $0x1234,0xdeadbeef </code></pre> <p>As there are no registers involved, this is the correct syntax for both <code>.att_syntax prefix</code> and <code>.att_syntax noprefix</code>, ie. embedded in C code, they look like this</p> <pre><code>__asm__(".att_syntax prefix"); __asm__("movl $0x1234,0xdeadbeef"); __asm__(".att_syntax noprefix"); __asm__("movl $0x1234,0xdeadbeef"); </code></pre> <p>You can optionally surround the address constant with parentheses, ie.</p> <pre><code>__asm__("movl $0x1234,(0xdeadbeef)"); </code></pre> <p>will work as well.</p> <p>When adding a sigil to a plain address constant, the code will fail to copile</p> <pre><code>__asm__("movl $0x1234,$0xdeadbeef"); // won't compile </code></pre> <p>When surrounding this expression with paranthesis, the compiler will emit wrong code without warning, ie</p> <pre><code>__asm__("movl $0x1234,($0xdeadbeef)"); // doesn't warn, but doesn't work! </code></pre> <p>This will incorrectly emit the instruction</p> <pre><code>movl $0x1234,0x0 </code></pre> <p>In Intel mode, an address constant has to be prefixed with a segment register as well as the operand size and the <code>PTR</code> 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 <code>ds</code> is used by default.</p> <p>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.</p> <p>In <code>prefix</code> mode, the segment register has to be prefixed with <code>%</code>, but only using brackets will still work. These are the different ways to generate the correct instruction:</p> <pre><code>__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! </code></pre> <p>Omitting both segment register and brackets will fail to compile</p> <pre><code>__asm__("mov DWORD PTR 0xdeadbeef,0x1234"); // won't compile </code></pre> <p>I'll mark this question as <em>community wiki</em>, so if you have anything useful to add, feel free to do so.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload