【发布时间】:2016-03-10 17:24:26
【问题描述】:
我使用的是 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 的第二个打印语句打印的值。但是,在添加命令之后它会打印 2。如果我改用 addl 命令,它也会打印 2。我使用的是 xv6 的最新稳定版本。所以,我真的不怀疑这是问题所在。有没有其他方法可以在内联汇编中添加两个数字?
基本上我需要将 16(%esp) 增加 4。
将代码编辑为:
__asm__("addl $8, 16(%esp)\t\n");
【问题讨论】:
-
@MichaelWalz 具体表示
printf确实不修改esp。但它很可能会修改ecx。 -
请注意,at&t 中没有
add,只是汇编器有时可以从操作数中推断出大小。如果你想将16(%esp)增加 4,然后执行addl $4, 16(%esp)并完成它。 -
你怎么知道它不起作用?从外观上看,
16(%esp)是返回地址,覆盖它是一个非常糟糕的主意,如果你遇到可能意味着它正在工作的崩溃。这闻起来像 XY 问题,你想做什么?请注意,处理程序的返回地址不是源,以防您想返回到其他地方,这不是这样做的方法。 -
@Jester 基本上我正在实现信号。在信号处理程序中,我正在计算 500 个信号所花费的时间。因此,当信号发生在 main 中时,我会增加信号的数量。如果该数字达到 500,那么我会增加堆栈中的返回地址,这样我就不会继续执行异常创建代码(除以 0)。然后,它从 main 中退出。
-
我不知道它在
xv6上是如何工作的,但在普通的 unix 系统中,处理程序的返回地址不是异常的来源。要返回别处,您不会弄乱返回地址,而是在上下文中更改实际的重新启动地址。