第三部分是关于GCC内联汇编
GCC内联汇编比较特殊
它是说我们怎么在C语言的开发环境中
来使用汇编代码
来写汇编代码
使得C和混编来混在一起来使用
称之为内联汇编
这个实际上是GCC很有特点的地方
有了内联汇编之后
可以直接很简洁的在C里面插入汇编代码
来完成相应的功能
那为什么要在C里面插汇编代码呢
大家想一想 其实是由于我们的C语言
不足以完成所有的CPU的指令
特别是有一些特权指令
它没有对应的C语言的对照
比如说我们刚才说的
加载全局描述符表 LGDT
这么一条机器指令 你没法用C语言表述
你只能用汇编来表述
在这种情况下 内联汇编会发生很大的作用
它可以很简单的在C语言里面写出一句话
来把这个功能给完成
这使得我们写的代码更加清楚
更加便于理解
好 我们接下来就来看看它是如何工作的
这也是我们需要去了解的
因为我们在uCore中有这种代码存在
所以说我们希望大家能够
通过对这部分的了解
能够读懂这个代码
从而可以更好的理解uCore的整个执行过程
这是一个例子
这是汇编代码 这是内联汇编
你可以看出来其实它们很像
这是汇编代码 把这个值赋给EAX的寄存器
那么对于我们来说 内联汇编怎么写呢
加了一个asm代表内联汇编的关键字
然后把刚才这段汇编括起来
括起来之后用引号表示字符串
还需要注意它这个标示里面
一个百分号变成两个百分号
这是一些语法上的一些表示而已
那其实还是很直接的对应
这是一种简单的对应方式 好理解
我们再看看 它的一个完整的格式是这样的
asm关键字 然后用一个括号
这里面这一段就是刚才说的字符串
还有三个约束表示
对于输出操作数 输入操作数
还有一个clobber
一个我们暂时可以忽略的一个表述
这三个表述都是可选的
你可以像刚才那样什么都不加
但是你如果要建立一定约束
比如说我希望把某一个变量
用某一个寄存器来表示
那么可以在里面加一定的约束
使得它完成现在的功能
我们会以例子来展示它大致的一个过程
好 这是一段代码片段 大家可以看看
这是取于我们uCore的代码
比如这是一个CR0的内存变量
我们希望把刚才说的CR0寄存器的
某一个bit给置位
怎么来做呢 CR0寄存器没法用C语言来表示
不得不用内联汇编来表示它
这里面写了两句话
比如说在这里面
首先把CR0的内容
读到这个%0寄存器里面去
然后这个寄存器的内容
最终会赋给CR0这个变量
这个=r 是大致这个含义
既然你把CR0寄存器的内容
读给了CR0这个变量
那我们可以对变量进行操作
把某一个位置成1
或了一下 或等于 置成1
之后我们再把内存里的内容
写回到CR0寄存器里面去
就靠这条指令来完成
可以看到 正好倒过来了
是要把CR0给一个寄存器
它会把这个寄存器的值赋给CR0寄存器
那我们生成汇编
如果我们把这段代码生成汇编
可以看到是不是我们刚才想达到的意思
CR0寄存器赋给ebx
ebx给到一个 这实际上是代表一个局部变量
然后这一步就是一个或操作
来完成了对某一个bit的置1
再把这个局部变量里面的值赋给EAX寄存器
最后把EAX赋给CR0
那就完成了这两个内联汇编的功能
可以看出来 这段代码比这段代码要复杂
因为这里面加了相应的约束之后
用我们的GCC编译器自动的
帮我们把关系给建立好
基于你刚才所谓的约束的规则
所以可以看出来
有了这么一个表示之后
我们可以更简洁的来完成
一些汇编才能完成的功能
前面已经讲到了 这里面一些关键字
volatile 是不需要做进一步的优化 调整顺序
那这个%0 代表的是第一个用到的寄存器
这个r代表是任意寄存器的意思
这里面都有相应的含义
来建立相应的约束
也意味着我们说用EBX
或者EAX来完成对CR0的传递
都是可以的 因为它这个值是r
这是一个约束的表示
那我们其实可以看一个更复杂的例子
这里有一系列的局部变量
然后会执行一个int 80的指令
这个int 80也是一个特殊的指令
产生我们说的软中断
这个过程需要把这些arg1赋给bx
arg2赋给cx arg3赋给dx
arg4赋给什么呢 ESI
不同的字符代表什么意思
这边有一个约束的约定
所以这条内联汇编
其实等同于这么一条指令
它最终是会把相应的
这些局部变量赋给相应的寄存器
然后调用int 80这么一个指令
产生一个软中断
最后这个软中断返回的值
会再赋给EBP
最后是把它赋给了这个地方
我们基本上就简单的
给大家介绍了一下内联汇编
如果大家需要去进一步了解内联汇编的话
也可以看一些相关的文档
这方面网上文档也比较多
大家可以去了解一下
这里面最主要的目标是
希望大家能够通过对这个的一个初步了解
能够知道uCore中出现的内联汇编
大致是什么含义
这是我们说去了解的一个最主要的目标