在gcc内联x86_64程序集中约束r10寄存器 [英] Constraining r10 register in gcc inline x86_64 assembly

查看:161
本文介绍了在gcc内联x86_64程序集中约束r10寄存器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在写一个重量很轻的libc替换库,以便我可以更好地了解内核-应用程序接口.首要任务显然是准备好一些系统调用包装器.我已经成功地使用了1到3个参数包装器,但是我正在为4个参数变量而苦苦挣扎.这是我的出发点:

I'm having a go at writing a very light weight libc replacement library so that I can better understand the kernel - application interface. The first task is clearly getting some system call wrappers in place. I've successfully got 1 to 3 argument wrappers working but I'm struggling with a 4 argument varient. Here's my starting point:

long _syscall4(long type, long a1, long a2, long a3, long a4)
{
    long ret;
    asm
    (
        "syscall"
        : "=a"(ret)
        : "a"(type), "D"(a1), "S"(a2), "d"(a3), "r10"(a4)
        : "c", "r11"
    );
    return ret;
}

编译器给我以下错误:

error: matching constraint references invalid operand number

我的_syscall3函数可以正常工作,但不使用r10或没有内容清单.

My _syscall3 function works fine but doesnt use r10 or have a clobber list.

有什么想法吗?

推荐答案

寄存器没有任何限制:%r8 .. %15.但是,最新版本(如gcc-4.x)应该接受:

There are no constraints for registers: %r8 .. %15. However, more recent (as in gcc-4.x) should accept:

register long r10 asm("r10") = a4;

然后将输入约束:"r" (r10)用于您的asm语句.
https://gcc.gnu.org/onlinedocs/gcc/Local- Register-Variables.html

then use the input constraint: "r" (r10) for your asm statement.
https://gcc.gnu.org/onlinedocs/gcc/Local-Register-Variables.html

请注意,强制为扩展asm强制选择"r"约束是GCC保证针对register-asm本地用户的 only 行为.像register void *rsp asm("rsp");void *stack_pointer = rsp;之类的东西有时可以工作,但是不能保证并且不再推荐.

Note that forcing the choice of an "r" constraint for Extended asm is the only behaviour that GCC guarantees for register-asm locals. Things like register void *rsp asm("rsp"); and void *stack_pointer = rsp; do sometimes work, but are not guaranteed and not recommended anymore.

您将要使syscall包装器asm语句为volatile并且具有"memory"遮盖符,除非您使用虚拟内存输入为特定的系统调用编写特定的包装器以知道哪些arg是指针,或输出(根据

You're going to want your syscall wrapper asm statement to be volatile and have a "memory" clobber, unless you write specific wrappers for specific system calls to know which args are pointers, using a dummy memory input or output (as per How can I indicate that the memory *pointed* to by an inline ASM argument may be used?)

它需要volatile,因为执行write(1, buf, 16)应该两次打印缓冲区,而不仅仅是 CSE 返回值!系统调用通常不是其输入的纯函数,因此您需要volatile.

It needs to volatile because doing write(1, buf, 16) should print the buffer twice, not just CSE the return value! System calls are in general not Pure functions of their inputs, so you need volatile.

(某些特定的系统调用包装器,例如getpid可能是非易失性的,因为除非您也使用fork,否则它们每次都会返回相同的东西.但是getpid如果通过VDSO完成,则效率更高,因此不会如果您使用的是Linux,则不必首先输入内核,因此,如果要为getpidclock_gettime创建自定义包装,则可能首先不需要syscall. Linux权威指南系统调用)

(Some specific system call wrappers like getpid could be non-volatile, because they do return the same thing every time, unless you also use fork. But getpid is more efficient if done through the VDSO so it doesn't have to enter the kernel in the first place if you're on Linux, so if you're making a custom wrapper for getpid and clock_gettime you probably don't want syscall in the first place. See The Definitive Guide to Linux System Calls)

之所以需要"memory"破坏器,是因为寄存器中的指针并不会暗示所指向的存储器也是输入或输出.存储到仅由write系统调用读取的缓冲区中,需要被优化为无效存储.或者对于munmap,编译器最好在未映射内存之前 已完成所有加载/存储.某些系统调用不需要任何指针输入,也不需要"memory",但是通用包装程序必须做出最坏的假设.

The "memory" clobber is needed because a pointer in a register does not imply that the pointed-to memory is also an input or output. Stores to a buffer that are only read by a write system call need to not be optimized away as dead stores. Or for munmap, the compiler had better have finished any loads/stores before the memory is unmapped. Some system calls don't take any pointer inputs, and don't need "memory", but a generic wrapper has to make worst-case assumptions.

register ... asm("r10")不需要 ,但需要syscall包装器.

register ... asm("r10") does not in general require asm volatile or "memory" clobbers, but a syscall wrapper does.

这篇关于在gcc内联x86_64程序集中约束r10寄存器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆