正常来说,系统调用传参顺序是
EDI, ESI, EDX, ECX, R8, R9
看clone的系统调用时,发现传参顺序为 EDI, ESI, EDX, R10, R8, R9, R12
请问有什么原因吗

正常来说,系统调用传参顺序是
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 Sep 15, 2020 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 Sep 16, 2020 via Android 用户模式调用约定( calling convention ) 是 EDI, ESI, EDX, ECX, R8, R9 内核模式调用约定( 系统调用 ) 是 rdi,rsi,rdx,r10,r8 和 r9 你用 c 写个 printf 的程序看下汇编就懂了。 |
5 chanchancl OP |