Go的Syscall()中的第二个`r2`返回值是多少?(What is the second `r2` return value in Go's Syscall() for?)

编程入门 行业动态 更新时间:2024-10-22 10:50:19
Go的Syscall()中的第二个`r2`返回值是多少?(What is the second `r2` return value in Go's Syscall() for?)

这是Go的无证Syscall功能 :

func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno)

这是C定义 :

long syscall(long number, ...);

很不一样。 所以很明显trap是number ,而a1 , a2和a3允许三个参数。 我还发现r1是返回值,而err是errno 。 但什么是r2 ? 系统调用手册页未提及多个返回值。

它确实给出了实际的调用约定(仍然只有一个retval):

arch/ABI instruction syscall # retval error Notes ──────────────────────────────────────────────────────────────────── alpha callsys v0 a0 a3 [1] arc trap0 r8 r0 - arm/OABI swi NR - a1 - [2] arm/EABI swi 0x0 r7 r0 - arm64 svc #0 x8 x0 - blackfin excpt 0x0 P0 R0 - i386 int $0x80 eax eax - ia64 break 0x100000 r15 r8 r10 [1] m68k trap #0 d0 d0 - microblaze brki r14,8 r12 r3 - mips syscall v0 v0 a3 [1] nios2 trap r2 r2 r7 parisc ble 0x100(%sr2, %r0) r20 r28 - powerpc sc r0 r3 r0 [1] s390 svc 0 r1 r2 - [3] s390x svc 0 r1 r2 - [3] superh trap #0x17 r3 r0 - [4] sparc/32 t 0x10 g1 o0 psr/csr [1] sparc/64 t 0x6d g1 o0 psr/csr [1] tile swint1 R10 R00 R01 [1] x86_64 syscall rax rax - [5] x32 syscall rax rax - [5] xtensa syscall a2 a2 -

但在x86上,这是实现

#define INVOKE_SYSCALL INT $0x80 TEXT ·Syscall(SB),NOSPLIT,$0-28 CALL runtime·entersyscall(SB) MOVL trap+0(FP), AX // syscall entry MOVL a1+4(FP), BX MOVL a2+8(FP), CX MOVL a3+12(FP), DX MOVL $0, SI MOVL $0, DI INVOKE_SYSCALL CMPL AX, $0xfffff001 JLS ok MOVL $-1, r1+16(FP) MOVL $0, r2+20(FP) NEGL AX MOVL AX, err+24(FP) CALL runtime·exitsyscall(SB) RET ok: MOVL AX, r1+16(FP) MOVL DX, r2+20(FP) MOVL $0, err+24(FP) CALL runtime·exitsyscall(SB) RET

现在,我没有很好地阅读汇编,但我很确定它在r2中返回EDX。 为什么?

Here is Go's undocumented Syscall function:

func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno)

And here is the C definition:

long syscall(long number, ...);

Pretty different. So it's fairly obvious that trap is number, and a1, a2, and a3 allow for three arguments. I also worked out that r1 is the return value, and err is errno. But what is r2? The syscall man page doesn't mention multiple return values.

It does give the actual calling conventions (still only one retval):

arch/ABI instruction syscall # retval error Notes ──────────────────────────────────────────────────────────────────── alpha callsys v0 a0 a3 [1] arc trap0 r8 r0 - arm/OABI swi NR - a1 - [2] arm/EABI swi 0x0 r7 r0 - arm64 svc #0 x8 x0 - blackfin excpt 0x0 P0 R0 - i386 int $0x80 eax eax - ia64 break 0x100000 r15 r8 r10 [1] m68k trap #0 d0 d0 - microblaze brki r14,8 r12 r3 - mips syscall v0 v0 a3 [1] nios2 trap r2 r2 r7 parisc ble 0x100(%sr2, %r0) r20 r28 - powerpc sc r0 r3 r0 [1] s390 svc 0 r1 r2 - [3] s390x svc 0 r1 r2 - [3] superh trap #0x17 r3 r0 - [4] sparc/32 t 0x10 g1 o0 psr/csr [1] sparc/64 t 0x6d g1 o0 psr/csr [1] tile swint1 R10 R00 R01 [1] x86_64 syscall rax rax - [5] x32 syscall rax rax - [5] xtensa syscall a2 a2 -

But on x86 this is the implementation

#define INVOKE_SYSCALL INT $0x80 TEXT ·Syscall(SB),NOSPLIT,$0-28 CALL runtime·entersyscall(SB) MOVL trap+0(FP), AX // syscall entry MOVL a1+4(FP), BX MOVL a2+8(FP), CX MOVL a3+12(FP), DX MOVL $0, SI MOVL $0, DI INVOKE_SYSCALL CMPL AX, $0xfffff001 JLS ok MOVL $-1, r1+16(FP) MOVL $0, r2+20(FP) NEGL AX MOVL AX, err+24(FP) CALL runtime·exitsyscall(SB) RET ok: MOVL AX, r1+16(FP) MOVL DX, r2+20(FP) MOVL $0, err+24(FP) CALL runtime·exitsyscall(SB) RET

Now, I don't read assembly too well, but I'm pretty sure it is returning EDX in r2. Why?

最满意答案

我认为它们具有多个返回值以保持一致性。 从该表中可以看出,某些体系结构返回多个值,如果从该目录中检查一些其他程序集文件,您将看到它们将寄存器值移动到r2。


但为何DX呢? 这部分仍然令人费解。 分散在网络上的是i386上提到的文档,允许函数使用EAX和EDX作为返回值。 例如, System V应用程序二进制接口Intel386架构处理器补充 :

%edx scratch scratch; 也用于返回某些64位返回类型的高32位

后来继续说:

%edx中返回最重要的32位。 在%eax中返回最小的无符号长long有效32位。

我们试试这个:

uint64_t some_function() { return 18446744073709551614LLU; }

Clang最终制作:

pushl %ebp movl %esp, %ebp movl $-2, %eax movl $-1, %edx popl %ebp ret

有趣的是, asm_linux_amd64.s似乎做了同样的事情,给我们一个借口来看看AMD64的System V ABI 。 关于RDX,这也是文件中提到的:

用于将第三个参数传递给函数; 第二个返回寄存器

但附录A具体涉及Linux约定。

C库和Linux内核之间的接口与用户级应用程序的接口相同,但有以下区别:

从系统调用返回, 寄存器%rax包含系统调用的结果。 介于-4095和-1之间的值表示错误,它是-errno。

没有提到系统调用的RDX。


我不会为了这个(或者一般)而把我的手放在火中但是我怀疑对于Linux来说没有必要使用DX,因为它没有利用它们从AX溢出的如此大的返回值。

I think they have multiple return values for consistency. As you can see from that table, some architectures return multiple values and if you check a few of the other assembly files from that directory you'll see they move register values to r2.


But why DX? This part is still puzzling. Scattered across the web are docs mentioning on i386 a function is allowed to use both EAX and EDX for return values. For example System V Application Binary Interface Intel386 Architecture Processor Supplement:

%edx scratch register; also used to return the upper 32bits of some 64bit return types

Later it goes on to say:

The most significant 32 bits are returned in %edx. The least unsigned long long significant 32 bits are returned in %eax.

Let's try this:

uint64_t some_function() { return 18446744073709551614LLU; }

Clang ends up producing:

pushl %ebp movl %esp, %ebp movl $-2, %eax movl $-1, %edx popl %ebp ret

Interestingly, asm_linux_amd64.s seems to do the same thing, giving us a pretext to look at the System V ABI for AMD64. This also doc mentions in passing, about RDX:

used to pass 3rd argument to functions; 2nd return register

But Appendix A deals with Linux Conventions specifically.

The interface between the C library and the Linux kernel is the same as for the user-level applications with the following differences:

Returning from the syscall, register %rax contains the result of the system-call. A value in the range between -4095 and -1 indicates an error, it is -errno.

No mention of RDX for the system call.


I won't put my hand in the fire for this (or in general) but I suspect taking DX is not necessary for Linux which doesn't make use of such large return values that they spill out of AX.

更多推荐

本文发布于:2023-07-06 07:58:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1047598.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:第二个   返回值   Syscall   return

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!