我使用的是xv6,它在x86机器上实现了原始的UNIX。我在C程序中编写了非常简单的内联汇编:
register int ecx asm ("%ecx");
printf(1, "%d\n", ecx);
__asm__("movl 16(%esp), %ecx\t\n");
printf(1, "%d\n", ecx);
__asm__("add $0, %ecx\t\n");
printf(1, "%d\n", ecx);
__asm__("movl %ecx, 16(%esp)\t\n");
我通常会得到第二个印刷语句打印的434之类的值。但是,在add命令之后它打印2.如果我使用addl命令,它也会打印2.我使用的是xv6的最新稳定版本。所以,我真的不怀疑它是问题所在。有没有其他方法可以在内联汇编中添加两个数字?
基本上我需要增加16(%esp)4。
编辑代码:
__asm__("addl $8, 16(%esp)\t\n");
答案 0 :(得分:1)
1)在你的例子中,你没有将ecx增加4,你将它递增0。
__asm__("addl $4, %ecx");
2)您应该能够将多个命令链接到一个asm调用
__asm__("movl 16(%esp), %ecx\n\t"
"addl $4, %ecx\n\t"
"movl %ecx, 16(%esp)");
3)register关键字是提示,编译器可能决定将你的变量放在任何它想要的地方。另外,阅读GCC页面上的文档会警告某些函数如何破坏各种寄存器。 printf()作为C函数可以很好地使用ecx寄存器而不保留其值。它可以保留它,但它可能不会;编译器可以使用该寄存器进行该调用内的各种优化。它是80x86上的通用寄存器,通常用于各种参数传递和返回值。
未经测试的更正:
int reg; // By leaving this out, we give GCC the ability to pick the best available register.
/*
* volatile indicates to GCC that this inline assembly might do odd side
* effects and should disable any optimizations around it.
*/
asm volatile ("movl 16(%esp), %0\n\t"
"addl $4, %0\n\t"
"movl %0, 16(%esp)"
: "r" (reg)); // The "r" indicates we want to use a register
printf("Result: %d\n", reg);
GCC manage page有更多详情。