gcc中的内联asm笔记(1)

  
uint16_t port;
uint8_t value;
...
asm volatile ("outb %1, %0" 
                :
                : "dN" (port), "a" (value)
               );

写玩具内核的时候看到要读写端口,接触到了gcc的内联汇编,如上,解释一下

outb %1, %0 表示把%1的内容写到%0对应的端口中去,%0和%1不是立即数的意思,它们代表的是后面的(port)和(value)的值,数字是根据它们的相对排列得来的,所以port是%0,value是%1。也就是说这条指令实际上就是 outb value, port的意思。

对于gcc的这种内联汇编的格式也在这里解释一下,可以看到和传统接触的 "movl %ebx ,%eax"有点点不同,格式是这样的

asm ( assembler template                /*指令表达式*/
        : output operands                  /* 输出变量 */
        : input operands                   /* 输入变量 */  
        : list of clobbered registers      /* 变化表 */  
 );  

指令表达式 就是类似与"movl %ebx, %eax"的表达式
输入变量代表的是这个变量在指令表达式中引用的时候作为结果存储输出的地方
输入变量代表的是这个变量在指令表达式中引用的时候作为提供输入的地方
变化表就不在这里细说了,可以参考文末链接中更加系统详细的说明

这里举个例子说明一下输入变量和输出变量
uint16_t port;
uint8_t ret; 
....
asm volatile("inb %1, %0" 
              : "=a" (ret) 
              : "dN" (port)
              );
inb  %1, %0 表示从 %1(port)中读取值存放到%0(ret)中去,可以理解成输入变量就是把变量值直接替换到指令中当成个立即数去使用,而输出变量就是把变量的地址替换到指令中当成一个地址去写, "=a"和"dN"是修饰想了解参考文末链接。

参考链接:
GCC-Inline-Assembly-HOWTO:http://blog.csdn.net/iamlbccc/article/details/7212837


  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
GCC内联汇编asm格式是一种将汇编代码嵌入到C或C++源代码的方法。它允许开发人员直接使用汇编语言来访问底层硬件或执行高性能算法。以下是GCC内联汇编asm格式的详细说明。 基本格式 GCC内联汇编asm格式基本格式如下: ```c asm (assembly code : output operands : input operands : clobbered registers); ``` - assembly code:汇编代码,可以是单行或多行代码。 - output operands:用于存储计算结果的变量,可以有多个,用逗号分隔。输出操作数是可选的,可以省略。 - input operands:用于传递参数的变量,可以有多个,用逗号分隔。输入操作数是必需的。 - clobbered registers:代码执行期间会被修改的寄存器,用于通知编译器。可以有多个,用逗号分隔。clobbered registers是可选的,可以省略。 示例 以下是一个简单的GCC内联汇编asm格式示例,将eax寄存器的值加1,并将结果存储在eax。 ```c int value = 10; asm ("addl $1, %%eax" : "=a" (value) : "a" (value)); ``` - "addl $1, %%eax":汇编代码,将eax加1。 - "=a" (value):输出操作数,将eax的值存储在value变量。 - "a" (value):输入操作数,将value的值传递给eax。 - 没有clobbered registers。 输出操作数 输出操作数用于将汇编代码的结果存储在变量。输出操作数有两种类型:普通输出(通道约束)和跨约束输出。 普通输出 普通输出使用“=约束”语法表示,其约束指定了输出操作数应存储在哪个寄存器或内存位置。约束可以是以下之一: - "=r"(任意寄存器) - "=m"(任意内存位置) - "=a"(eax寄存器) - "=d"(edx寄存器) - "=q"(eax或edx寄存器) 示例 以下是一个使用普通输出的示例,将eax寄存器的值加1,并将结果存储在value变量。 ```c int value; asm ("addl $1, %%eax" : "=a" (value) : "a" (value)); ``` 跨约束输出 跨约束输出是一种将结果存储在多个输出变量的方法。它使用“+约束”语法表示,其约束指定了输出操作数应存储在哪个寄存器或内存位置。多个约束可以用逗号分隔。 示例 以下是一个使用跨约束输出的示例,将eax寄存器的值加1,并将结果存储在value1和value2变量。 ```c int value1, value2; asm ("addl $1, %%eax" : "+a" (value1), "=r" (value2)); ``` 输入操作数 输入操作数用于将变量的值传递给汇编代码。输入操作数使用“约束”语法表示,其约束指定了变量应该存储在哪个寄存器或内存位置。约束可以是以下之一: - "r"(任意寄存器) - "m"(任意内存位置) - "a"(eax寄存器) - "d"(edx寄存器) - "q"(eax或edx寄存器) 示例 以下是一个使用输入操作数的示例,将value变量的值传递给eax寄存器。 ```c int value = 10; asm ("movl %0, %%eax" : : "r" (value)); ``` clobbered registers clobbered registers是在汇编代码执行期间会被修改的寄存器列表。它用于通知编译器哪些寄存器应该被保存和恢复。clobbered registers使用“%约束”语法表示,其约束指定了被修改的寄存器名称。多个寄存器可以用逗号分隔。 示例 以下是一个使用clobbered registers的示例,将eax寄存器的值加1,并告诉编译器edx寄存器也被修改了。 ```c asm ("addl $1, %%eax" : : "a" (value) : "%edx"); ``` 总结 GCC内联汇编asm格式是一种将汇编代码嵌入到C或C++源代码的方法。它允许开发人员直接使用汇编语言来访问底层硬件或执行高性能算法。通过输出操作数、输入操作数和clobbered registers,开发人员可以管理汇编代码与C或C++代码之间的数据流和寄存器使用。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值