【发布时间】:2019-08-28 08:04:55
【问题描述】:
我有一个修改“ecx”(或任何其他寄存器)的函数(C)
int proc(int n) {
int ret;
asm volatile ("movl %1, %%ecx\n\t" // mov (n) to ecx
"addl $10, %%ecx\n\t" // add (10) to ecx (n)
"movl %%ecx, %0" /* ret = n + 10 */
: "=r" (ret) : "r" (n) : "ecx");
return ret;
}
现在我想在另一个函数中调用这个函数,该函数在调用“proc”函数之前在“ecx”中移动一个值
int main_proc(int n) {
asm volatile ("movl $55, %%ecx" ::: "ecx"); /// mov (55) to ecx
int ret;
asm volatile ("call proc" : "=r" (ret) : "r" (n) : "ecx"); // ecx is modified in proc function and the value of ecx is not 55 anymore even with "ecx" clobber
asm volatile ("addl %%ecx, %0" : "=r" (ret));
return ret;
}
在这个函数中,(55) 被移入“ecx”寄存器,然后调用“proc”函数(修改“ecx”)。在这种情况下,“proc”函数必须先推送“ecx”并在最后弹出它,但它不会发生!!!! 这是具有 (-O3) 优化级别的程序集源
proc:
movl %edi, %ecx
addl $10, %ecx
movl %ecx, %eax
ret
main_proc:
movl $55, %ecx
call proc
addl %ecx, %eax
ret
为什么 GCC 不使用 (push) 和 (pop) 进行“ecx”注册?我也用过"ecx" clobber !!!!!!
【问题讨论】:
-
您正在手动编写程序集。您如何期望 c 编译器知道您正在调用一个函数?
-
只是不要编写内联汇编。这几乎从不值得。
-
因为 C 编译器不解释程序集,所以它不知道里面有调用。
-
不,不是。这是你的职责。 GCC 只保存自己可能被破坏的数据; 不是您放在内联汇编块中的数据。 GCC 怎么会知道
asm volatile ("movl $55, %%ecx" ::: "ecx");将一些东西保存到ECX以后需要的东西?它可能只是用不再需要的临时内容覆盖ECX。 -
@Jason 当您插入自己的程序集时,GCC 没有更多的责任。 GCC 是一个 C 编译器,不会解释您的汇编语言。您对一切负责。如果您不想这样做,请改为编写 C 代码。 :-)
标签: c gcc x86 inline-assembly