关于lab1课件上第31页“gcc内联汇编-Example 2”的解释
匿名2023/07/31 19:52:01提问
应向勇老师要求,我整理了课后和老师讨论的结果。
以下是原课件内容:
看到这个example当时我有一个疑问,就是为什么要有中间的ebx和eax寄存器进行过渡,还要移到栈上进行再进行或操作。
比如为什么不能是这样的?(简称“m1”)
;m1
movl %cr0, 12(%esp)
orl $-2147483648, 12(%esp)
movl 12(%esp), %cr0
或者这样(“m2”)
;m2
movl %cr0, %ebx
orl $-2147483648, %ebx
movl %ebx, %cr0
下面我先对每句c代码进行解释,并说明相对应的汇编代码:
uint32_t cr0; // 无对应汇编,但gcc会给cr0分配存储单元,这里在栈上 -> 12(%esp)
asm volatile ("movl %%cr0, %0\n" :"=r"(cr0));
/*
movl %cr0, %ebx
movl %ebx, 12(%esp)
将cr0寄存器内容移动到cr0变量 -> 12(%esp)
之所以要两步是
1. 因为cr0是控制寄存器,不能和栈(内存)直接操作,需要寄存器进行过渡(解释了m1的错误)
2. 存到栈上是因为可能后面还需要用到cr0变量,所以把这临时变量分配到了栈上(解释了m2)
3. 同时编译器为了忠实地实现每步内联汇编的内容,不再进一步优化代码
*/
cr0 |= 0x80000000; // orl $-2147483648, 12(%esp),即把cr0最前面一位置1
asm volatile ("movl %0, %%cr0\n" ::"r"(cr0));
/*
movl 12(%esp), %eax
movl %eax, %cr0
将变量cr0的内容移到cr0寄存器上,需要两步的原因同上
*/