GCC内联汇编

概述

在开发操作系统过程中,有时必须使用某些特殊的指令(如inb/outb/hlt),而C编译器无法自动使用这些指令。因此,如果要使用这些指令,有两种方式:
在汇编文件中为该指令的使用创建汇编函数(子程序),然后在C代码中以函数调用的方式去使用;
使用内联汇编:即在C代码中嵌入汇编程序。
在大多数情况下,使用内联汇编会更加简单、易用。因此,本文简要介绍本课程中所用的相关的GCC内联汇编的写法。

基本格式

基本格式如下,以asm关键字开头,包含3个可选的配置项。

asm (汇编语句
    : 输出操作数(可选)
    : 输入操作数(可选)
    : 被破坏的寄存器列表(可选)
    );
下面举个例子,其功能为将a的值赋值给b,具体代码如下:
int a = 10 , b ; 
asm ( "movl %1, %%eax; movl %%eax, %0;" 
     : "=r" ( b )         /* 输出 */ 
     : "r" ( a )          /* 输入 */ 
     : "%eax"          /* 破坏寄存器 */ 
     ) ;

其效果等价于movl a, %%eax; movl %%eax, b,即将a的值先给eax寄存器,再将eax寄存器的值给到b,最终实现b = a的效果。

具体格式说明

只有一条汇编语句
在内联汇编中,可以只有汇编语句,即没有输出、输入操作数,没有被破坏的寄存器列表。例如:
asm ( "hlt" ) ; // 让CPU暂停运行
有多条汇编语句
当有多条汇编语句时,需要写在同一字符串中,不同语句之间用;或者\n\t分隔。

asm (  "sti; hlt"  ) ;          // 开启中断,然后让CPU暂停运行
asm (  "sti\n\thlt"  ) ;    // 开启中断,然后让CPU暂停运行
asm (  "sti\n\t"             // 同上。C语言中多个连续的字符串,会被认为是同一字符串
             "hlt"  ) ;              // 开启中断,然后让CPU暂停运行

有输出操作数

当汇编语句中有些数据需要存储到C语言中的某些变量中时,则可以使用输出操作数。
例如,下面的代码是将c变量的值通过mov $3, c设置成3。其中%[out]为定义的一个输出约束,其名称应与:后的out相同,“=r"©指定了c变量映射到某个寄存器中。
char c;
asm(“mov $3, %[out]”:[out]”=r"©);
其中=r还可以设置成其它,如下表所示:
r:任意寄存器
a:%eax, %ax, %al
b: %ebx, %bx, %bl
c: %ecx, %cx, %cl
d: %edx, %dx, %dl
S: %esi, %si
D: %edi, %di
通过上述方式,即实现了类似mov $3, c的效果。

有输入操作数

当需要从C语言中读取变量的值到汇编语句中时,则需要使用输入操作数。例如,下面的代码中,mov %[ch], %%al用于将c变量中的字符写到al中。因此,在输入操作数中使用了[ch]"r"©,即c变量映射到某个寄存器上(见上文中输出操作数的类似设置)。最终的效果为:mov $0xe, %%ah、mov %[c], %%al

char c = 'a';
asm (
	"mov $0xe, %%ah\n\t"
	"mov %[ch], %%al\n\t"
	"int $0x10"::[ch]"r"(c));

避免优化

在某些情况下,GCC编译器会对内联汇编中的汇编语句进行优化处理,最终导致生成语句和预期的不同,影响程序的执行结果。为了避免这些问题,可以强制要求GCC不对其进行优化,即原样的生成。要达到这点,可以使用__asm__ __volatile__替代原来的asm。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值