文档
注册

例外场景示例

使用intel、at&t混合汇编风格

对于嵌入式汇编,gcc支持不同的汇编风格,使用“{…|…}”区分,以下例子是使用了at&t和intel两种汇编风格的嵌入式汇编代码块,当前工具仅支持at&t的汇编风格转换。

at&t和intel风格差异如下:

表1 at&t和intel风格差异

场景

at&t

intel

说明

操作寄存器

%eax

eax

at&t使用寄存器需要带%符号

操作立即数

mov $imm,%eax

mov ebx,imm

at&t使用立即数需要带$符号

源/目的操作数顺序

movl %eax,%ebx

mov ebx,eax

at&t目的操作数在后,源操作数在前

内存寻址方式

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):
    );
}

使用goto标签

以下例子是使用goto标签的嵌入式汇编代码块:

 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;
}

使用段寄存器

以下例子是使用段寄存器ds的嵌入式汇编代码块:

 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"
    );
}

使用未赋值的物理寄存器

以下例子是使用了未赋值寄存器的嵌入式汇编代码块,寄存器eax在使用前未赋值,会导致运行结果不可知。

1
2
3
4
5
6
7
8
9
void unassigned_register()
{
    int output = 0;
    __asm__(
        "movl %%eax, %0\n\t"
        :"=r"(output)
        :
    );
}

使用全局符号

以下例子是使用了全局符号的嵌入式汇编代码块,全局变量Foo和外部标签out_label,对于第一个汇编代码块来说,都是全局符号。

 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"
    );
}

输入输出变量的位宽大于128位

以下例子是使用了大于128位变量的嵌入式汇编代码块,输出变量(result)的类型是__m256i,其位宽为256位,大于128位,由于ARM架构没有128位以上的寄存器,使用超过128位的变量,会导致汇编器传参出错,工具无法处理x86和Kunpeng两个平台之间的这种传参差异。

 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"
    );
}

使用.byte机器码

以下例子是使用.byte机器码的嵌入式汇编代码块,请将机器码手动修改为对应的汇编指令再重新扫描转换。注意,汇编不支持迁移修改后再次扫描指的是全汇编文件(.s和.S),含嵌入式汇编的文件支持修改后重新扫描。

 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);
}

机器码转汇编指令可以通过在已经安装好llvm-mc的环境,执行如下llvm-mc命令完成:

1
echo "机器码" | llvm-mc -disassemble -show-inst --triple=x86_64

例如,本例中的.byte机器码使用llvm-mc转换结果如下:

图1 转换结果

其中,llvm-mc转机器码得到的汇编指令中类似eax的寄存器操作数仅含有一个“%”,而嵌入式汇编中寄存器需要两个“%”,因此本例中的机器码".byte 0xb8, 0xe5, 0x07, 0x00, 0x00"最终修改成的汇编指令是"movl $2021, %%eax"。

搜索结果
找到“0”个结果

当前产品无相关内容

未找到相关内容,请尝试其他搜索词