我们可以看到asm volatile这样的使用,当我们查看的时候,我们可以发现其调用关系大抵如下:
__asm__ 是 asm的宏定义, 因此有时候我们可以看到这样的使用:
#define __asm__ asm
以上的开头是为了让我们了解什么是内联汇编,下面则是该种方法的使用:
首先需要知道的是,所谓内联汇编可以简单理解为在高级语言中“嵌入”了汇编语言,因此叫“内联”。
同时volatile的目的是告知内联汇编:如果我volatile存在,你不许给我优化,但是我不在,你可以,你是自由的。
其中asm的使用规则为:
(1) 可以为空: asm volatile(""); 或asm ("")
(2) asm("crc32 %%ebx, %%eax\n\t" : "=a" (initval) : "b" (data), "a" (initval));
__asm__ __volatile__("InSTructiON List" : Output : Input : Clobber/Modify);
这里我们在此看一下这条命令,我们将举例和模板对比着看,我们 可以进行这个对比:
(1) crc32 %%ebx, %%eax是指令list,也就是说是我们的指令;
(2). =a(initval) 是我们的输出
(3). b 是我们的输入
第一个问题,是不是所有的:之间的内容都必须存在呢,或者说有没有可以省略的部分呢
答案是,内容自然可以省略,想我们上边的(1),但是即使内容可以省略,可是冒号却无法省略,事实上我们也知道,这样的用法即使是在JAVA中,也是很常见的。但是,有一种例外,即当我们的最后一个,也就是改动寄存器不写时,是可以省略最后的冒号的。
当然看到这里,想必大家一定开始有所思考,那么我们可以一一对应了,可是细节呢?
没问题,接下来细节讲解如下所示:
首先我们看到的是= ,那么什么是= , = 表明只能写入操作数 ,和他并列的用法有以下这些:
+ 可读可写,大家都知道计算机里+是一个很具有宽容性的符号对吧
= 只能写入, 我=你, 你写入了
% 操作数甚至可以和下一个操作数切换 ,什么是%,在计算机里可以认为他是取模,取模可以循环着来,那么%自然也可以变来变去,不过这只是个人的理解
& 在内联函数完成前,可以删除或者重新使用操作数 &就是指针吗,指针当然可以有更多自由,像是删除或是重新使用都可以了。
开头已经知道了,那么什么是a,什么是b,也就是说,我们任何时候,先得知道我们有什么权利,我们的限制是多少,接下来呢,我们要知道的是我们对谁有权利,那么对谁有呢?这就是后边的作用了:
a使用a系的寄存器,如eax ax al。。。
b使用b系的寄存器,
c使用c系的寄存器
d使用d系的寄存器
S使用 esi 或者si
D 使用edi 或者di
r 使用任何一个通用寄存器(因为r是register,我猜的)
q 使用eax,ebx,ecx,edx 是quarter也就是32位4字的,这里附一张csapp的图
A 是使用eax和edx来存储一个64bit的值
m 是使用memory内存的值
o 是使用内存偏移量(offset)
V 是只是用直接内存映射(Valid)
i 是使用直接的立即数(immediate)
n 是使用直接已知数值的立即数(number)
g是使用任意一个寄存器或者内存的位置 (global)