Rate This Document
Findability
Accuracy
Completeness
Readability

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.

Table 1 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:

Figure 1 Conversion result

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.