gpt4 book ai didi

go - Go 的 Syscall() 中的第二个 `r2` 返回值是做什么用的?

转载 作者:IT王子 更新时间:2023-10-29 00:42:01 26 4
gpt4 key购买 nike

这里是 Go's undocumented Syscall function :

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

这里是 the C definition :

long syscall(long number, ...);

完全不同。所以很明显 trapnumbera1a2a3 允许三个参数。我还算出r1是返回值,errerrno。但是 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 上这是 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

现在,我不太了解汇编,但我很确定它会在 r2 中返回 EDX。为什么?

最佳答案

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


但为什么是 DX?这部分仍然令人费解。散布在网络上的文档提到在 i386 上允许函数同时使用 EAX 和 EDX 作为返回值。例如System V Application Binary Interface Intel386 Architecture Processor Supplement :

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

后来它继续说:

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

让我们试试这个:

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似乎在做同样的事情,给我们一个看System V ABI for AMD64的借口.这也顺便提到了 RDX:

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

但附录 A 专门处理 Linux 约定。

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.

没有提及系统调用的 RDX。


我不会为此(或一般情况下)插手,但我怀疑 Linux 没有必要使用 DX,因为 Linux 不使用从 AX 溢出的如此大的返回值。

关于go - Go 的 Syscall() 中的第二个 `r2` 返回值是做什么用的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38738534/

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