杂记:GCC内联汇编

此生再无相见时 提交于 2020-12-13 14:00:58

Author: retrhelo

Date: 2020.12.13

转载请注明出处

注意,本文仅基于GCC编译器,不确认是否在其他编译器环境下有效。

1. 使用asm()语句在C语言中嵌入汇编代码

我们可以使用asm()语句或是__asm__()语句来嵌入汇编代码。通常来说这两者的用法是相同的。其使用方法如下所示

asm ( "assembly code"
	 : output operands                  /* optional */
	 : input operands                   /* optional */
	 : list of clobbered registers      /* optional */
);

1.1 Assembly Code(汇编代码)

这一部分用于填入所要执行的汇编代码,通常按照C风格字符串的格式填入,在不同的语句之间要填入\n作为换行符。

1.2 Outputs Operands(输出操作数)

这一部分视具体情况而言是可选的。通常使用形如"=r" (var)的形式编写代码,以将寄存器和变量联系起来。其中,r可以使用具体的字符来指定所使用的寄存器,其规则如下表所示 | r | Registers | | :------------: | :------------: | | a | %eax, %ax, %al | | b | %ebx, %bx, %bl | | c | %ecx, %cx, %cl | | d | %edx, %dx, %dl | | S | %esi, %si | | D | %edi, %di | 上表描述了在x86_64架构下的相关情况,在其他架构下具体详见GCC官方手册。

1.3 Input Operands(输入操作数)

这部分同样是可选的(Optional),在具体编程时可根据情况选择。输入操作数部分通常使用形如"r" (var)的规则编写。同样的,r可以替换成上表中的某个具体字符来使用特定的寄存器。

1.4 Example

#include <stdio.h>

int main() {

    int arg1, arg2, add, sub, mul, quo, rem ;

    printf( "Enter two integer numbers : " );
    scanf( "%d%d", &arg1, &arg2 );

    /* Perform Addition, Subtraction, Multiplication & Division */
    __asm__ ( "addl %%ebx, %%eax;" : "=a" (add) : "a" (arg1) , "b" (arg2) );
    __asm__ ( "subl %%ebx, %%eax;" : "=a" (sub) : "a" (arg1) , "b" (arg2) );
    __asm__ ( "imull %%ebx, %%eax;" : "=a" (mul) : "a" (arg1) , "b" (arg2) );

    __asm__ ( "movl $0x0, %%edx;"
              "movl %2, %%eax;"
              "movl %3, %%ebx;"
               "idivl %%ebx;" : "=a" (quo), "=d" (rem) : "g" (arg1), "g" (arg2) );

    printf( "%d + %d = %d\n", arg1, arg2, add );
    printf( "%d - %d = %d\n", arg1, arg2, sub );
    printf( "%d * %d = %d\n", arg1, arg2, mul );
    printf( "%d / %d = %d\n", arg1, arg2, quo );
    printf( "%d %% %d = %d\n", arg1, arg2, rem );

    return 0 ;
}

参考文献

[1] https://www.codeproject.com/articles/15971/using-inline-assembly-in-c-c

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!