gpt4 book ai didi

内联汇编访问系统时间后C段错误

转载 作者:太空宇宙 更新时间:2023-11-03 23:19:51 25 4
gpt4 key购买 nike

我一直在尝试在 Ubuntu 16.04 下使用 C 中的内联汇编来访问系统时间。我的代码如下所示:

struct timeval *date_time;

asm(
"movl $116, %%eax;"
"push $0;"
"push %0;"
"push $0;"
"int $0x80;"
:
:"b"(date_time)
);

假设我在特定函数中存储了上面的几行。每当我调用该函数时,它都会触发错误代码:

Segmentation fault (core dumped)

由于我是内联汇编的新手,我猜代码可能有问题。因此,如果您能指出我做错了什么,我将非常高兴。感谢您的所有建议。

最佳答案

这里有很多错误,其中最重要的是:

  • 您将东西压入堆栈,但在离开内联汇编 block 之前没有再次弹出它们。编译器不知道你这样做了,所以它会在错误的地方寻找堆栈上的所有东西(比如返回地址)。这很可能是导致崩溃的原因。

  • 更一般地说,使用这种内联汇编风格的编译器根本不解释汇编指令。他们相信你正确地使用了输入、输出、破坏注解。如果您甚至忘记提及已修改的一个寄存器或内存区域,编译器将围绕汇编插入生成不正确的代码,程序将无法运行。

  • “Ubuntu 16.04”是 Linux 的一个发行版,因此您使用了错误的调用约定。 Linux 在寄存器中获取系统调用参数,而不是在堆栈中,as documented here ,并且 gettimeofday 不是 x86-32/Linux 上的系统调用号 116。 (始终使用 SYS_foo 常量,来自 sys/syscall.h,用于系统调用号。)

此外,最好在实际插入的程序集中尽可能少。在这种情况下,这仅意味着 int 指令本身。相反,使用输入和输出约束设置参数。这为编译器提供了最大的优化余地。 (如果你手写汇编是因为编译器没有足够好的优化工作,你应该写一个完整的纯汇编的“.s”文件,而不是一个带有巨大汇编插入的.c文件;这更可维护。)

这个任务的正确代码应该是这样的

#include <assert.h>
#include <sys/time.h>
#include <sys/syscall.h>

struct timeval
call_gettimeofday()
{
struct timeval ret;
int dummy;
asm("int $0x80"
: "=m" (ret), "=a" (dummy)
: "1" (SYS_gettimeofday), "b" (&ret), "c" (0));
assert(!dummy); // gettimeofday should never fail
return ret;
}

最后一点,使用内联汇编进行系统调用几乎总是错误的。 C 库的包装函数可能做的工作比你所看到的要多,而且它们知道如何使用更有效的陷阱序列(使用 sysentersyscall 而不是 int) 在可能的情况下。在 gettimeofday 的情况下,差异更为深刻:C 库知道如何执行 gettimeofday 操作,根本不会陷入内核!(阅读 vDSO 以了解这是如何实现的。)

关于内联汇编访问系统时间后C段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43321395/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com