1.前言
本文主要对GCC内嵌汇编一文的简要总结,试着用自己的话把GCC汇编的关键点描述出来,以验证自己是否真正理解。本文将以《Linux内核完全注释 v3》中的一个例子进行描述,这个例子我看的时候是非常的懵逼,直到看了GCC内嵌汇编一文。
2. 实例说明
GCC内嵌汇编的基本结构
__asm ("汇编语句列表"
:输出寄存器
:输入寄存器
:会被修改的寄存器);
-
汇编语句列表
就是普通的一组汇编语句; -
输出寄存器
表示寄存器的数据赋值给一个表达式作为输出。
注:
(1) 出现在输入寄存器或输出寄存器括号中的内容称为表达式, 如上例中__res,seg和*(addr)
(2) 在输入寄存器或输出寄存器中如果有多个表达式将用逗号隔开
(3)从输出寄存器到输入寄存器所出现的表达式将依次编号,如上例中__res被编号为0, seg被编号为1, *(addr)被编号为2,依次类推。
上例中输出寄存器为:
“=a” (__res) ,此处a代表将eax寄存器加载到表达式,也就是__res中,=表示输出
-
输入寄存器
表示表达式的值赋值给寄存器作为输入。
上例中:
“0” (seg), “m” (*(addr)), 此处的0表示与表达式0使用同样的寄存器,而表达式0为__res它使用eax寄存器,所以seg也将使用eax寄存器,即seg会赋值给eax -
会被修改的寄存器
是告诉编译器这里面出现的寄存器会被修改,请不要占用。
所以如上语句进行翻译如下:
register char __res; //定义寄存器变量__res
push %fs //将fs寄存器入栈
mov %ax, %fs //将eax的内容赋值给fs, 而通过输入寄存器可知eax内容为seg,因此也就是将seg
//的内容赋值给%fs
movb %fs:%2, %al // %2为表达式2即*(addr), 因此是将seg:*(addr)的1字节内容放到al寄存器
pop %fs //恢复fs的值
综上就是将从seg段偏移addr的地方取一个字节
参考文档
- https://blog.youkuaiyun.com/littlehedgehog/article/details/2259665
GCC内嵌汇编