386-64系统函数调用ABI规范
一、了解该规范的作用
在看C/C++文件对应的反汇编代码中,比较关键的就是找到函数的传入参数,而这个本身并没有神秘之处,完全是ABI已经明确规定过的。这里再次整理下,方便之后查阅。
二、文档
《System V Application Binary Interface AMD64 Architecture Processor Supplement Draft Version 0.99.7》
其中对于函数参数传递说明为3.2.3 Parameter Passing
Passing Once arguments are classified, the registers get assigned (in left-to-right order) for passing as follows:
1. If the class is MEMORY, pass the argument on the stack.
2. If the class is INTEGER, the next available register of the sequence %rdi,%rsi, %rdx, %rcx, %r8 and %r9 is used.
3. If the class is SSE, the next available vector register is used, the registers are taken in the order from %xmm0 to %xmm7.
4. If the class is SSEUP, the eightbyte is passed in the next available eightbyte chunk of the last used vector register.
5. If the class is X87, X87UP or COMPLEX_X87, it is passed in memory
这里通常来说,就是整数(bool、指针、整数)按照%rdi,%rsi, %rdx, %rcx, %r8 and %r9的方式优先使用寄存器,浮点数按照%xmm0 to %xmm7使用寄存器,不能通过寄存器存储的通过栈传递。
对于C++来说,由于this指针作为成员函数的隐藏指针,所以归入“整数”类型,也意味着在类成员函数调用中,第一个通用寄存器rdi存储的是this指针。
三、例子
tsecer@harry: cat funccall.cpp
int pr(...);
struct S
{
int x, y;
S foo(int x, int y, float f, double d, S s)
{
S rs;
rs.x = pr(this->x, this->y, x, y, f, d ,s);
return rs;
}
};
void foo()
{
S s;
s.foo(1, 2, 1., .1, s);
}
tsecer@harry: g++ -S funccall.cpp -fverbose-asm
tsecer@harry: cat funccall.s
.file "funccall.cpp"
# GNU C++ (GCC) version 4.8.5 20150623 (Red Hat 4.8.5-4) (x86_64-redhat-linux)
# compiled by GNU C version 4.8.5 20150623 (Red Hat 4.8.5-4), GMP version 5.1.1, MPFR version 3.1.1, MPC version 1.0.1
# warning: GMP header version 5.1.1 differs from library version 6.0.0.
# GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
# 传递的选项: -D_GNU_SOURCE funccall.cpp -mtune=generic
# -march=x86-64 -fverbose-asm
# 启用的选项: -faggressive-loop-optimizations
# -fasynchronous-unwind-tables -fauto-inc-dec -fbranch-count-reg -fcommon
# -fdelete-null-pointer-checks -fdwarf2-cfi-asm -fearly-inlining
# -feliminate-unused-debug-types -fexceptions -ffunction-cse -fgcse-lm
# -fgnu-runtime -fgnu-unique -fident -finline-atomics -fira-hoist-pressure
# -fira-share-save-slots -fira-share-spill-slots -fivopts
# -fkeep-static-consts -fleading-underscore -fmath-errno
# -fmerge-debug-strings -fmove-loop-invariants -fpeephole
# -fprefetch-loop-arrays -freg-struct-return
# -fsched-critical-path-heuristic -fsched-dep-count-heuristic
# -fsched-group-heuristic -fsched-interblock -fsched-last-insn-heuristic
# -fsched-rank-heuristic -fsched-spec -fsched-spec-insn-heuristic
# -fsched-stalled-insns-dep -fshow-column -fsigned-zeros
# -fsplit-ivs-in-unroller -fstrict-volatile-bitfields -fsync-libcalls
# -ftrapping-math -ftree-coalesce-vars -ftree-cselim -ftree-forwprop
# -ftree-loop-if-convert -ftree-loop-im -ftree-loop-ivcanon
# -ftree-loop-optimize -ftree-parallelize-loops= -ftree-phiprop -ftree-pta
# -ftree-reassoc -ftree-scev-cprop -ftree-slp-vectorize
# -ftree-vect-loop-version -funit-at-a-time -funwind-tables -fverbose-asm
# -fzero-initialized-in-bss -m128bit-long-double -m64 -m80387
# -maccumulate-outgoing-args -malign-stringops -mfancy-math-387
# -mfp-ret-in-387 -mfxsr -mglibc -mieee-fp -mlong-double-80 -mmmx -mno-sse4
# -mpush-args -mred-zone -msse -msse2 -mtls-direct-seg-refs
.section .text._ZN1S3fooEiifdS_,"axG",@progbits,_ZN1S3fooEiifdS_,comdat
.align 2
.weak _ZN1S3fooEiifdS_
.type _ZN1S3fooEiifdS_, @function
_ZN1S3fooEiifdS_:
.LFB0:
.cfi_startproc
pushq %rbp #
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp #,
.cfi_def_cfa_register 6
subq $64, %rsp #,
movq %rdi, -24(%rbp) # this, this
movl %esi, -28(%rbp) # x, x
movl %edx, -32(%rbp) # y, y
movss %xmm0, -36(%rbp) # f, f
movsd %xmm1, -48(%rbp) # d, d
movq %rcx, -64(%rbp) # s, s
movss -36(%rbp), %xmm0 # f, D.2251
cvtps2pd %xmm0, %xmm0 # D.2251, D.2251
movq -24(%rbp), %rax # this, tmp65
movl 4(%rax), %esi # this_3(D)->y, D.2252
movq -24(%rbp), %rax # this, tmp66
movl (%rax), %edi # this_3(D)->x, D.2252
movq -64(%rbp), %r8 # s, tmp67
movq -48(%rbp), %rax # d, tmp68
movl -32(%rbp), %ecx # y, tmp69
movl -28(%rbp), %edx # x, tmp70
movq %rax, -56(%rbp) # tmp68, %sfp
movsd -56(%rbp), %xmm1 # %sfp,
movl $2, %eax #,
call _Z2prz #
movl %eax, -16(%rbp) # D.2252, rs.x
movq -16(%rbp), %rax # rs, D.2244
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size _ZN1S3fooEiifdS_, .-_ZN1S3fooEiifdS_
.text
.globl _Z3foov
.type _Z3foov, @function
_Z3foov:
.LFB1:
.cfi_startproc
pushq %rbp #
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp #,
.cfi_def_cfa_register 6
subq $32, %rsp #,
movq -16(%rbp), %rdx # s, tmp60
movabsq $4591870180066957722, %rax #, tmp61
leaq -16(%rbp), %rdi #, tmp62
movq %rdx, %rcx # tmp60,
movq %rax, -24(%rbp) # tmp61, %sfp
movsd -24(%rbp), %xmm1 # %sfp,
movss .LC1(%rip), %xmm0 #,
movl $2, %edx #,
movl $1, %esi #,
call _ZN1S3fooEiifdS_ #
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE1:
.size _Z3foov, .-_Z3foov
.section .rodata
.align 4
.LC1:
.long 1065353216
.ident "GCC: (GNU) 4.8.5 20150623 (Red Hat 4.8.5-4)"
.section .note.GNU-stack,"",@progbits
tsecer@harry: