Exception Scenarios
Using the Mixed Intel and AT&T Syntaxes
GCC supports different assembly syntaxes in inline assembly. The assembly syntaxes of different types are separated by {...|...}. In the following example, Intel and AT&T syntaxes are used. The tool, however, supports only the AT&T syntax.
The following lists the differences between the AT&T syntax and Intel syntax.
|
Category |
AT&T |
Intel |
Description |
|---|---|---|---|
|
Registers |
%eax |
eax |
The register names in AT&T syntax must be prefixed with %. |
|
Immediates |
mov $imm, %eax |
mov eax, imm |
The immediates in AT&T syntax must be prefixed with $. |
|
Source/Destination operand sequence |
movl %eax, %ebx |
mov ebx, eax |
In AT&T syntax, the destination operand follows the source operand. |
|
Memory addressing mode |
disp(base, index, scale) |
base+index*scale+disp |
- |
1 2 3 4 5 6 7 8 9 10 |
void multiple_assembler_dialects() { int a = 10; int b = 101; __asm__( "add{l %[int_b], %[out_a] | %[out_a], %[int_b]}" :[out_a]"+r"(a) :[int_b]"r"(b): ); } |
Using the goto Label
The following is an example of an inline assembly code block that uses the goto label:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
int goto_label(int a, int b) { __asm__ goto( "cmp %0, %1\n\t" "jb %l[label]\n\t" : : "r"(a), "r"(b) : : label ); return a; label: return b; } |
Using Segment Registers
The following is an example of an inline assembly code block that uses the ds segment register:
1 2 3 4 5 6 7 8 9 10 |
void segment_register(unsigned int *base, unsigned long index) { int output = 0; __asm__( "movl %%ds:%c4(%1, %3, 4), %0\n\t" :"=r"(output) :"r"(base), "r"(output), "r"(index), "i"(4) :"eax" ); } |
Using a Physical Register with No Value
In the following example, the eax register is not assigned a value before being used. Consequently, the result is unpredictable.
1 2 3 4 5 6 7 8 9 |
void unassigned_register() { int output = 0; __asm__( "movl %%eax, %0\n\t" :"=r"(output) : ); } |
Using Global Symbols
In the following example, the global variable Foo and the external label out_label are global symbols for the first assembly code block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
int Foo[] = {100, 101, 102}; void global_symbol() { int output = 0; __asm__( "movl 4+Foo, %0\n\t" "jmp out_label\n\t" :"=r"(output) : ); __asm__( "out_label:\n\t" ); } |
Bit Width of Input and Output Variables Greater Than 128
In the following example, the type of the output variable (result) is __m256i, and the bit width is 256 bits. The Arm architecture does not have registers greater than 128 bits. If variables greater than 128 bits are used, the assembler cannot transfer parameters properly. The tool cannot handle the parameter transfer difference between the x86 and Kunpeng platforms.
1 2 3 4 5 6 7 8 9 10 11 |
void variable_width(unsigned int *ymmData) { __m256i result; __asm__( "vmovups %1, %%ymm1\n\t" "vmovups %%ymm1, %0 \n\t" :"=m"(result) :"m"(ymmData) :"ymm1" ); } |
Using .byte Machine Code
The following example is an inline assembly code block using .byte machine code. Manually change the machine code to the corresponding assembly instruction and then scan and convert the code again. Note that pure assembly files (.s or .S) cannot be re-scanned after porting and modification. Inline assembly files can be re-scanned after being modified.
1 2 3 4 5 6 7 8 9 10 |
void byte_assembler_code() { int dst; asm (".byte 0xb8, 0xe5, 0x07, 0x00, 0x00\n\t" : "=a" (dst) : : ); printf("dst = %d\n", dst); } |
You can run the following command in the environment where llvm-mc has been installed to convert machine code into assembly instructions.
1
|
echo "Machine_code" | llvm-mc -disassemble -show-inst --triple=x86_64 |
For example, the .byte machine code in this section is converted using llvm-mc as follows:
In the assembly instruction converted from the machine code by using llvm-mc, the register operand similar to eax contains only one percent sign (%), but the register in the inline assembly needs two percent signs (%). Therefore, the final assembly instruction converted from the machine code .byte 0xb8, 0xe5, 0x07, 0x00, 0x00 in this example is movl $2021, %%eax.