由于基本内联汇编功能太薄弱了,所以才对它进行了扩展以使其功能强大。不过,易用性往往与功能强弱是成正比的,如您所料,扩展内联汇编确实有点难,但在求知欲的驱使下,就让咱们痛并快乐着吧。
gcc本身是个c编译器,要让其支持汇编语言,必然牵扯到以下问题:
- 在内联汇编代码插入点之前的c代码,其编译后也要被分配寄存器等资源,插入的汇编代码也要使用寄存器,这是否会造成资源冲突?
- 汇编语言如何访问c代码中的变量?
您看,内联汇编真不是简单地写两句汇编代码就完事了,所以,很多同学宁可单独写纯汇编文件再链接,也不愿意写内联汇编,也许您现在还不服,一会可就说不准喽^_^。
咱们从头分析,假设目前没有扩展内联汇编:
当汇编代码嵌入到c代码中,如果汇编代码想把c代码中的变量做为操作数加载到寄存器,如何找到可用的寄存器,这可是个大问题,程序员并不知道哪个寄存器已经被分配了,哪些寄存器是空闲的。即使知道了寄存器的分配情况也还不够,有些底层操作,对寄存器的要求是固定的(比如in/out指令,就得使用al做为数据寄存器),万一那个固定的寄存器已经被占用了,咱们在使用前还得把它备份。
也许您觉得,这些问题不难啊,我不管之前用了哪些寄存器,我在内联汇编中用哪些寄存器时就先将其入栈备份,用完了再恢复呗。听上去不错,但由用户来保证数据完整性简直就是灾难,人的精力是有限的,谁知道会不会漏掉哪个寄存器呢,而且在出了问题后也不容易查出来。再说,运行中有大量的压栈操作,访问内存本身就比较慢,不如在编译阶段由编译器优化,直接分配给寄存器或用寄存器缓存,这样程序运行才更快。所以,这类事情还是交给编译器自己做这事才放心。
既然编译器对咱们不放心,那么现在的问题变成了如何将c代码中的变量变成汇编代码中的操作数,由于编译器无法预测用户的需求,这些只得让用户控制,故编译器采取的做法是,它提供一个模板,让用户在模板中提出要求,其余工作由它负责实现。这些用户提出的要求,就是后面所说的约束。