正常来说,系统调用传参顺序是
EDI, ESI, EDX, ECX, R8, R9
看clone的系统调用时,发现传参顺序为 EDI, ESI, EDX, R10, R8, R9, R12
请问有什么原因吗
1
chanchancl OP 比较了一下,发现我手里的 go1.15.1 的源码,和连接里的 go1.15.2 的代码又不一样了。。。
这些寄存器里到底哪些是传参的。。哪些是作为共享用的呢? |
2
chanchancl OP 以 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. 这有什么原因吗? |
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) ------------------------------------------------------------------------------------------------ |
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 的程序看下汇编就懂了。 |
5
chanchancl OP |