Notes of Inline Assembly
Table of Contents
1 The syntax comparation of Intel ASM and AT&T ASM
- Register Naming For AT&T ASM, register names are prefixed with '%'
1: - AT&T: %eax 2: - Intel: eax
- Source & Destination ordering The source is always at left and the destination is always at right.
1: - AT&T: movl %eax, %ebx 2: - Intel: mov ebx, eax
- Constant value or immediate value format Should be prefixed with '$' The below example is to set 'eax' to '3'
1: - AT&T: movl $0x3, %eax 2: - Intel: mov eax, 0x3
The below example moves 'C' defined variable 'boo' to 'eax'
1: - AT&T: movl $_boo, %eax 2: - Intel: mov eax, _boo
- Operator size specification You must suffix you instruction with one of 'b', 'w', 'l' to specify your destination register width as a 'byte', 'word' or 'longword'. Otherwise, the GNU assembler will guess.
1: - AT&T: movw %ax, %bx 2: - Intel: mov bx, ax
- Referencing memory C language: immd32[base + index * scale]
1: - AT&T: immd32(base, index, scale) 2: - Intel: [base + index * scale + immd32] 3: + Address particular C variable 4: - AT&T: (_boo) 5: - Intel: [_boo] 6: + Address what register point to 7: - AT&T: (%eax) 8: - Intel: [eax] 9: + Address a variable offeset by the value of a register 10: - AT&T: _foo(%eax) 11: - Intel: [eax + _foo] 12: + Address a value in a array of integer 13: - AT&T: _array(,%eax,4) 14: - Intel: [eax * 4 + _array]
2 Basic inline assembly
2.1 'asm'
The basic inline assembly is very simple
- asm("statements");
- For exmaple:
- asm("nop");
- asm("movl %eax, %ebx");
- For exmaple:
1: asm ("pushl %eax\n\t" 2: "movl $0, %eax\n\t" 3: "popl %eax");
2.2 '__asm__'
If 'asm' conficts with something keywords in your program, you could use
1: __asm__("statements");
2.3 '__asm__ __volatile__'
If you don't want your assembly to be optimized by assembler, add volatile keyword.
3 Extended inline assembly
- The extended assembly allows input arguments and output arguments. The basic
format is as below:
1: Format: 2: asm ("statements : output_registers : input_registers : clobbered_registers") 3: For the clobbered_reisters, it means that you cannot count on these registers. 4: Their values may change. 5: Example: 6: asm ("cld\n\t" 7: "rep\n\t" 8: "stosl" 9: : /* no output registers */ 10: : "c" (count), "a" (fill_value), "D" (dest) 11: : "%ecx", "%edi" );
- The list of register loading code which could be used.
a eax b ebx c ecx d edx S esi D edi I constant value (0 to 31) q,r dynamically allocated register (see below) g eax, ebx, ecx, edx or variable in memory A eax and edx combined into a 64-bit integer (use long longs) - The differences between 'q' and 'r' in the table
- 'q' makes GCC to allocate 'eax', 'ebx', 'ecx' and 'edx'
- 'r' makes GCC also consider 'esi' and 'edi'
3.1 Some examples
1: // Disable interrupt 2: #define disable() __asm__ __volatile__ ("cli"); 3: 4: // Enable interrupt 5: #define enable() __asm__ __volatile__ ("sti"); 6: 7: // arg2 = arg1 + arg1 * 4; 8: #define times5(arg1, arg2) \ 9: __asm__ ( \ 10: "leal (%0,%0,4),%0" \ 11: : "=r" (arg2) \ 12: : "0" (arg1) ); 13: 14: // arg2 = arg1 + arg1 * 8; 15: #define times9(arg1, arg2) \ 16: __asm__ ( \ 17: "leal (%0,%0,8),%0" \ 18: : "=r" (arg2) \ 19: : "0" (arg1) ); 20:
- For the {%n}, it is straightforward first-come-first-serve, left-to-right thing, mapping to 'q' and 'r'.
- So it will be "0", "1", "2" … etc
1: asm ("leal (%%ebx,%%ebx,4), %%ebx" 2: : "=b" (x) 3: : "b" (x) );
- If you want to use reigters in extended assemly, you should prefix the register with "%%" not just "%".