V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
chanchancl
V2EX  ›  Go 编程语言

关于 go 在 Linux , amd64 平台下的系统调用问题

  •  
  •   chanchancl · 2020-09-15 16:00:21 +08:00 · 1587 次点击
    这是一个创建于 1290 天前的主题,其中的信息可能已经有所发展或是发生改变。

    正常来说,系统调用传参顺序是

    EDI, ESI, EDX, ECX, R8, R9

    clone的系统调用时,发现传参顺序为 EDI, ESI, EDX, R10, R8, R9, R12

    请问有什么原因吗

    5 条回复    2020-09-16 14:59:05 +08:00
    chanchancl
        1
    chanchancl  
    OP
       2020-09-15 16:15:33 +08:00
    比较了一下,发现我手里的 go1.15.1 的源码,和连接里的 go1.15.2 的代码又不一样了。。。
    这些寄存器里到底哪些是传参的。。哪些是作为共享用的呢?
    chanchancl
        2
    chanchancl  
    OP
       2020-09-15 16:48:23 +08:00
    以 1.15 branch 作为标准

    [clone]( https://github.com/golang/go/blob/release-branch.go1.15/src/runtime/sys_linux_amd64.s#L592)

    从这里来看,R8, R9, R12 都被后面新创建的 client thread 使用了

    [clone system call]( https://man7.org/linux/man-pages/man2/clone.2.html)

    从 man page 看 clone 系统调用有 4 个参数。。。之前看错了。。。一直以为 clone 有 7 个参数

    那么刚好对应 DI, SI, DX R10,分别是 int (*fn)(void *), void *stack, int flags, void *arg

    这个问题大体上是解决了

    剩下的一个小问题就是, 为什么不用 CX 和 R11

    注释里有说

    // Careful: Linux system call clobbers CX and R11.

    这有什么原因吗?
    katsusan
        3
    katsusan  
       2020-09-15 18:40:46 +08:00
    linux 内核文档写的很清楚,RCX 和 R11 会在 x86_64 系统调用时被内核使用。

    --------------------------------------arch/x86/entry.S-------------------------------------
    * 64-bit SYSCALL saves rip to rcx, clears rflags.RF, then saves rflags to r11,
    * then loads new ss, cs, and rip from previously programmed MSRs.
    * rflags gets masked by a value from another MSR (so CLD and CLAC
    * are not needed). SYSCALL does not save anything on the stack
    * and does not change rsp.
    *
    * Registers on entry:
    * rax system call number
    * rcx return address
    * r11 saved rflags (note: r11 is callee-clobbered register in C ABI)
    * rdi arg0
    * rsi arg1
    * rdx arg2
    * r10 arg3 (needs to be moved to rcx to conform to C ABI)
    * r8 arg4
    * r9 arg5
    * (note: r12-r15, rbp, rbx are callee-preserved in C ABI)
    ------------------------------------------------------------------------------------------------
    Mohanson
        4
    Mohanson  
       2020-09-16 09:53:27 +08:00 via Android
    用户模式调用约定( calling convention ) 是 EDI, ESI, EDX, ECX, R8, R9

    内核模式调用约定( 系统调用 ) 是 rdi,rsi,rdx,r10,r8 和 r9

    你用 c 写个 printf 的程序看下汇编就懂了。
    chanchancl
        5
    chanchancl  
    OP
       2020-09-16 14:59:05 +08:00
    @katsusan @Mohanson 多谢各位的解答,原来调用普通函数和系统调用的传参顺序也不一样
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   952 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 21:06 · PVG 05:06 · LAX 14:06 · JFK 17:06
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.