汇编语言基础知识总结(六)

272 阅读2分钟

「这是我参与11月更文挑战的第18天,活动详情查看:2021最后一次更文挑战」。

C语言内嵌汇编代码(GCC内联汇编)

格式

asm volatile(   ;asm也可写成 __asm__ 或者__asm
"汇编指令"
:"=限制符"(输出参数) ,"=限制符"(输出参数)
:"限制符"(输入参数)
:保留列表
)

;volatile是可选关键字,表示禁止编译器对汇编代码进行优化
;汇编指令之间使用\n进行分隔
;限制符用于和c语言交互,属于可选,多个参数使用逗号进行分隔

代码示例:

//将input的值赋值给result 
int main()
{
    int result = 0;
    int input = 1;
  asm volatile (
        "movl %1, %0\n" // 通过占位符指定交互的变量  %1赋值给%0
        : "=r"(result)      // 输出变量,与汇编交互
        : "r"(input)            // 输入变量,与汇编交互
// 这里的r指示编译器自动将通用寄存器关联到变量
        );
     printf("result = %d\n", result);
    printf("input = %d\n", input);
 
 
}

我们看到,movl指令的操作数(operand)中,出现了%1、%0,这往往让新手摸不着头脑。其实只要知道下面的规则就不会产生疑惑了:

在内联汇编中,操作数通常用数字来引用,具体的编号规则为:若命令共涉及n个操作数,则第1个输出操作数(the first output operand)被编号为0,第2个output operand编号为1,依次类推,最后1个输入操作数(the last input operand)则被编号为n-1。

具体到上面的示例代码中,根据上下文,涉及到2个操作数变量a、b,这段汇编代码的作用是将a的值赋给b,可见,a是input operand,而b是output operand,那么根据操作数的引用规则,不难推出,a应该用%1来引用,b应该用%0来引用。

常用限制符参照:

限制符说明
r通用寄存器
aeax,ax,al
bebx,bx,bl
cecx,cx,cl
dedx,dx,dl
Sesi,si
Dedi,di
q寄存器a,b,c,d
m使用合法的内存代表参数
g任意寄存器,内存,立即数

为什么有些汇编语法不一致

C语言外链汇编

新建一个汇编原文件, linux平台.s结尾 ,windows平台.asm结尾


;外链汇编
;以下使用的是AT&T的汇编语法

.text ;声明为代码段
.global _sum  ;定义为全局函数, 否则无法被外界访问
_sum:  ;函数名称必须_开头
    movq %rdi,%rax  ;方法参数存放在di和di寄存器中
    addq %rsi,%rax
    retq

然后在C中进行相应调用即可