【发布时间】:2013-04-06 12:56:19
【问题描述】:
我正在尝试编写一个非常轻量级的 libc 替换库,以便更好地理解内核 - 应用程序接口。第一个任务显然是让一些系统调用包装器到位。我已经成功地让 1 到 3 个参数包装器工作,但我正在努力处理 4 个参数变量。这是我的出发点:
long _syscall4(long type, long a1, long a2, long a3, long a4)
{
long ret;
asm
(
"syscall"
: "=a"(ret) // return value
: "a"(type), "D"(a1), "S"(a2), "d"(a3), "r10"(a4)
: "c", "r11", "memory" // some syscalls read or write memory
// the syscall insn instruction itself destroys RCX and R11
);
return ret;
}
(编者注:这是安全且可用的,也是一个很好的例子,在应用答案的方式来处理r10之后。MUSL libc 有一些类似的宏。)
编译器给我以下错误:
error: matching constraint references invalid operand number
我的 _syscall3 函数工作正常,但不使用 r10 或有一个 clobber 列表。
(编者注:没有clobber列表是不安全的:您需要告诉编译器RCX和R11被覆盖,并且“内存”应该在系统调用之前同步,可以读取或写入内存。如果您想为特定的系统调用编写特定的包装器,您可以选择性地省略"memory" clobbers,或者根据哪些参数是该系统调用的指针来使用虚拟内存操作数。
如果这个_syscall4 函数不能内联,那么寄存器和"memory" clobbers 在实践中不会造成任何问题,但是您应该使它们能够内联;与调用非内联包装函数相比,内联此系统调用在调用站点需要的代码更少。)
【问题讨论】:
-
这应该在标题中(使用
inline关键字),以便它可以内联,从而节省调用站点将调用号放入 RDI 并将 args 放入其他 arg 传递的开销regs,然后被叫方在将索书号复制到 RAX 后将它们全部复制一份。我编辑添加了一个"memory"clobber 以确保安全。 (非内联函数调用已经隐含地成为优化器的内存屏障。)
标签: c gcc x86-64 system-calls inline-assembly