Back to Top

x64 传参试验(未完待续)

测试代码

void test_arg(int a, float b, int c, long double d, double e)
{
    int a1 = a;
    float b1 = b;
    int c1 = c;
    long double d1 = d;
    double e1 = e;
}

void test_varg(int a, ...)
{
    va_list vl;
    va_start(vl, a);

    int a1 = a;
    float b1 = (float)va_arg(vl, double);
    int c1 = va_arg(vl, int);
    long double d1 = va_arg(vl, long double);
    double e1 = va_arg(vl, double);
    va_end(vl);
}

int main (void)
{
    int a = 1;
    float b = 2.0f;
    int c = 3;
    long double d = 4.0;
    double e = 5.0;
    test_arg(a, b, c, d, e);
    test_varg(a, b, c, d, e);
    return 0;
}

反汇编(gcc2.8.5 gcc xxx.c -g -O0)

00000000004004f0 <_Z8test_argified>:
#include <stdio.h>
#include <stdarg.h>   

void test_arg(int a, float b, int c, long double d, double e)
{
4004f0:	55                   	push   %rbp
4004f1:	48 89 e5             	mov    %rsp,%rbp
4004f4:	89 7d cc             	mov    %edi,-0x34(%rbp)
4004f7:	f3 0f 11 45 c8       	movss  %xmm0,-0x38(%rbp)
4004fc:	89 75 c4             	mov    %esi,-0x3c(%rbp)
4004ff:	f2 0f 11 4d b8       	movsd  %xmm1,-0x48(%rbp)
    int a1 = a;
400504:	8b 45 cc             	mov    -0x34(%rbp),%eax
400507:	89 45 fc             	mov    %eax,-0x4(%rbp)
    float b1 = b;
40050a:	8b 45 c8             	mov    -0x38(%rbp),%eax
40050d:	89 45 f8             	mov    %eax,-0x8(%rbp)
    int c1 = c;
400510:	8b 45 c4             	mov    -0x3c(%rbp),%eax
400513:	89 45 f4             	mov    %eax,-0xc(%rbp)
    long double d1 = d;
400516:	48 8b 45 10          	mov    0x10(%rbp),%rax
40051a:	8b 55 18             	mov    0x18(%rbp),%edx
40051d:	48 89 45 e0          	mov    %rax,-0x20(%rbp)
400521:	89 55 e8             	mov    %edx,-0x18(%rbp)
    double e1 = e;
400524:	48 8b 45 b8          	mov    -0x48(%rbp),%rax
400528:	48 89 45 d8          	mov    %rax,-0x28(%rbp)
}
40052c:	5d                   	pop    %rbp
40052d:	c3                   	retq   

000000000040052e <_Z9test_vargiz>:

void test_varg(int a, ...)
{
40052e:	55                   	push   %rbp
40052f:	48 89 e5             	mov    %rsp,%rbp
400532:	48 83 ec 7c          	sub    $0x7c,%rsp
400536:	48 89 b5 58 ff ff ff 	mov    %rsi,-0xa8(%rbp)
40053d:	48 89 95 60 ff ff ff 	mov    %rdx,-0xa0(%rbp)
400544:	48 89 8d 68 ff ff ff 	mov    %rcx,-0x98(%rbp)
40054b:	4c 89 85 70 ff ff ff 	mov    %r8,-0x90(%rbp)
400552:	4c 89 8d 78 ff ff ff 	mov    %r9,-0x88(%rbp)
400559:	84 c0                	test   %al,%al
40055b:	74 20                	je     40057d <_Z9test_vargiz+0x4f>
40055d:	0f 29 45 80          	movaps %xmm0,-0x80(%rbp)
400561:	0f 29 4d 90          	movaps %xmm1,-0x70(%rbp)
400565:	0f 29 55 a0          	movaps %xmm2,-0x60(%rbp)
400569:	0f 29 5d b0          	movaps %xmm3,-0x50(%rbp)
40056d:	0f 29 65 c0          	movaps %xmm4,-0x40(%rbp)
400571:	0f 29 6d d0          	movaps %xmm5,-0x30(%rbp)
400575:	0f 29 75 e0          	movaps %xmm6,-0x20(%rbp)
400579:	0f 29 7d f0          	movaps %xmm7,-0x10(%rbp)
40057d:	89 bd 0c ff ff ff    	mov    %edi,-0xf4(%rbp)
    va_list vl;
    va_start(vl, a);
400583:	c7 85 10 ff ff ff 08 	movl   $0x8,-0xf0(%rbp)
40058a:	00 00 00 
40058d:	c7 85 14 ff ff ff 30 	movl   $0x30,-0xec(%rbp)
400594:	00 00 00 
400597:	48 8d 45 10          	lea    0x10(%rbp),%rax
40059b:	48 89 85 18 ff ff ff 	mov    %rax,-0xe8(%rbp)
4005a2:	48 8d 85 50 ff ff ff 	lea    -0xb0(%rbp),%rax
4005a9:	48 89 85 20 ff ff ff 	mov    %rax,-0xe0(%rbp)

    int a1 = a;
4005b0:	8b 85 0c ff ff ff    	mov    -0xf4(%rbp),%eax
4005b6:	89 85 4c ff ff ff    	mov    %eax,-0xb4(%rbp)
    float b1 = (float)va_arg(vl, double);
4005bc:	8b 85 14 ff ff ff    	mov    -0xec(%rbp),%eax
4005c2:	3d b0 00 00 00       	cmp    $0xb0,%eax
4005c7:	73 23                	jae    4005ec <_Z9test_vargiz+0xbe>
4005c9:	48 8b 95 20 ff ff ff 	mov    -0xe0(%rbp),%rdx
4005d0:	8b 85 14 ff ff ff    	mov    -0xec(%rbp),%eax
4005d6:	89 c0                	mov    %eax,%eax
4005d8:	48 01 d0             	add    %rdx,%rax
4005db:	8b 95 14 ff ff ff    	mov    -0xec(%rbp),%edx
4005e1:	83 c2 10             	add    $0x10,%edx
4005e4:	89 95 14 ff ff ff    	mov    %edx,-0xec(%rbp)
4005ea:	eb 15                	jmp    400601 <_Z9test_vargiz+0xd3>
4005ec:	48 8b 95 18 ff ff ff 	mov    -0xe8(%rbp),%rdx
4005f3:	48 89 d0             	mov    %rdx,%rax
4005f6:	48 83 c2 08          	add    $0x8,%rdx
4005fa:	48 89 95 18 ff ff ff 	mov    %rdx,-0xe8(%rbp)
400601:	f2 0f 10 00          	movsd  (%rax),%xmm0
400605:	66 0f 14 c0          	unpcklpd %xmm0,%xmm0
400609:	66 0f 5a c8          	cvtpd2ps %xmm0,%xmm1
40060d:	f3 0f 11 8d 48 ff ff 	movss  %xmm1,-0xb8(%rbp)
400614:	ff 
    int c1 = va_arg(vl, int);
400615:	8b 85 10 ff ff ff    	mov    -0xf0(%rbp),%eax
40061b:	83 f8 30             	cmp    $0x30,%eax
40061e:	73 23                	jae    400643 <_Z9test_vargiz+0x115>
400620:	48 8b 95 20 ff ff ff 	mov    -0xe0(%rbp),%rdx
400627:	8b 85 10 ff ff ff    	mov    -0xf0(%rbp),%eax
40062d:	89 c0                	mov    %eax,%eax
40062f:	48 01 d0             	add    %rdx,%rax
400632:	8b 95 10 ff ff ff    	mov    -0xf0(%rbp),%edx
400638:	83 c2 08             	add    $0x8,%edx
40063b:	89 95 10 ff ff ff    	mov    %edx,-0xf0(%rbp)
400641:	eb 15                	jmp    400658 <_Z9test_vargiz+0x12a>
400643:	48 8b 95 18 ff ff ff 	mov    -0xe8(%rbp),%rdx
40064a:	48 89 d0             	mov    %rdx,%rax
40064d:	48 83 c2 08          	add    $0x8,%rdx
400651:	48 89 95 18 ff ff ff 	mov    %rdx,-0xe8(%rbp)
400658:	8b 00                	mov    (%rax),%eax
40065a:	89 85 44 ff ff ff    	mov    %eax,-0xbc(%rbp)
    long double d1 = va_arg(vl, long double);
400660:	48 8b 85 18 ff ff ff 	mov    -0xe8(%rbp),%rax
400667:	48 83 c0 0f          	add    $0xf,%rax
40066b:	48 83 e0 f0          	and    $0xfffffffffffffff0,%rax
40066f:	48 89 c2             	mov    %rax,%rdx
400672:	48 83 c0 10          	add    $0x10,%rax
400676:	48 89 85 18 ff ff ff 	mov    %rax,-0xe8(%rbp)
40067d:	48 8b 02             	mov    (%rdx),%rax
400680:	8b 52 08             	mov    0x8(%rdx),%edx
400683:	48 89 85 30 ff ff ff 	mov    %rax,-0xd0(%rbp)
40068a:	89 95 38 ff ff ff    	mov    %edx,-0xc8(%rbp)
    double e1 = va_arg(vl, double);
400690:	8b 85 14 ff ff ff    	mov    -0xec(%rbp),%eax
400696:	3d b0 00 00 00       	cmp    $0xb0,%eax
40069b:	73 23                	jae    4006c0 <_Z9test_vargiz+0x192>
40069d:	48 8b 95 20 ff ff ff 	mov    -0xe0(%rbp),%rdx
4006a4:	8b 85 14 ff ff ff    	mov    -0xec(%rbp),%eax
4006aa:	89 c0                	mov    %eax,%eax
4006ac:	48 01 d0             	add    %rdx,%rax
4006af:	8b 95 14 ff ff ff    	mov    -0xec(%rbp),%edx
4006b5:	83 c2 10             	add    $0x10,%edx
4006b8:	89 95 14 ff ff ff    	mov    %edx,-0xec(%rbp)
4006be:	eb 15                	jmp    4006d5 <_Z9test_vargiz+0x1a7>
4006c0:	48 8b 95 18 ff ff ff 	mov    -0xe8(%rbp),%rdx
4006c7:	48 89 d0             	mov    %rdx,%rax
4006ca:	48 83 c2 08          	add    $0x8,%rdx
4006ce:	48 89 95 18 ff ff ff 	mov    %rdx,-0xe8(%rbp)
4006d5:	48 8b 00             	mov    (%rax),%rax
4006d8:	48 89 85 28 ff ff ff 	mov    %rax,-0xd8(%rbp)
    va_end(vl);
}
4006df:	c9                   	leaveq 
4006e0:	c3                   	retq   

00000000004006e1 <main>:

int main (void)
{
4006e1:	55                   	push   %rbp
4006e2:	48 89 e5             	mov    %rsp,%rbp
4006e5:	48 83 ec 50          	sub    $0x50,%rsp
    int a = 1;
4006e9:	c7 45 fc 01 00 00 00 	movl   $0x1,-0x4(%rbp)
    float b = 2.0f;
4006f0:	8b 05 3a 01 00 00    	mov    0x13a(%rip),%eax        # 400830 <__dso_handle+0x8>
4006f6:	89 45 f8             	mov    %eax,-0x8(%rbp)
    int c = 3;
4006f9:	c7 45 f4 03 00 00 00 	movl   $0x3,-0xc(%rbp)
    long double d = 4.0;
400700:	48 b8 00 00 00 00 00 	movabs $0x8000000000000000,%rax
400707:	00 00 80 
40070a:	ba 01 40 00 00       	mov    $0x4001,%edx
40070f:	48 89 45 e0          	mov    %rax,-0x20(%rbp)
400713:	89 55 e8             	mov    %edx,-0x18(%rbp)
    double e = 5.0;
400716:	48 b8 00 00 00 00 00 	movabs $0x4014000000000000,%rax
40071d:	00 14 40 
400720:	48 89 45 d8          	mov    %rax,-0x28(%rbp)
    test_arg(a, b, c, d, e);
400724:	48 8b 75 d8          	mov    -0x28(%rbp),%rsi
400728:	44 8b 45 f4          	mov    -0xc(%rbp),%r8d
40072c:	8b 4d f8             	mov    -0x8(%rbp),%ecx
40072f:	8b 7d fc             	mov    -0x4(%rbp),%edi
400732:	48 8b 45 e0          	mov    -0x20(%rbp),%rax
400736:	8b 55 e8             	mov    -0x18(%rbp),%edx
400739:	48 89 04 24          	mov    %rax,(%rsp)
40073d:	89 54 24 08          	mov    %edx,0x8(%rsp)
400741:	48 89 75 c8          	mov    %rsi,-0x38(%rbp)
400745:	f2 0f 10 4d c8       	movsd  -0x38(%rbp),%xmm1
40074a:	44 89 c6             	mov    %r8d,%esi
40074d:	89 4d c8             	mov    %ecx,-0x38(%rbp)
400750:	f3 0f 10 45 c8       	movss  -0x38(%rbp),%xmm0
400755:	e8 96 fd ff ff       	callq  4004f0 <_Z8test_argified>
    test_varg(a, b, c, d, e);
40075a:	f3 0f 10 45 f8       	movss  -0x8(%rbp),%xmm0
40075f:	0f 5a c0             	cvtps2pd %xmm0,%xmm0
400762:	48 8b 4d d8          	mov    -0x28(%rbp),%rcx
400766:	8b 75 f4             	mov    -0xc(%rbp),%esi
400769:	8b 7d fc             	mov    -0x4(%rbp),%edi
40076c:	48 8b 45 e0          	mov    -0x20(%rbp),%rax
400770:	8b 55 e8             	mov    -0x18(%rbp),%edx
400773:	48 89 04 24          	mov    %rax,(%rsp)
400777:	89 54 24 08          	mov    %edx,0x8(%rsp)
40077b:	48 89 4d c8          	mov    %rcx,-0x38(%rbp)
40077f:	f2 0f 10 4d c8       	movsd  -0x38(%rbp),%xmm1
400784:	b8 02 00 00 00       	mov    $0x2,%eax
400789:	e8 a0 fd ff ff       	callq  40052e <_Z9test_vargiz>
    return 0;
40078e:	b8 00 00 00 00       	mov    $0x0,%eax
}

结论

根据文档mpx-linux64-abi P20

  1. If the class is MEMORY, pass the argument on the stack.
  2. If the class is INTEGER or POINTER, the next available register of the sequence %rdi, %rsi, %rdx, %rcx, %r8 and %r9 is used13.
  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.

    int a edi edi float b xmm0 xmm0 int c rsi rcx long double d 内存 内存 double e xmm1 xmm1