关于lab1课件上第31页“gcc内联汇编-Example 2”的解释
匿名2023/07/31 19:52:01提问
    lab1student
226

应向勇老师要求,我整理了课后和老师讨论的结果。

以下是原课件内容:

看到这个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寄存器上,需要两步的原因同上
*/
回答(2
    推荐问答
      Simple Empty
      暂无数据