美文网首页
Linux X86架构参数传递规则

Linux X86架构参数传递规则

作者: BlueBlueSummer | 来源:发表于2019-05-08 13:02 被阅读0次

背景

突然好奇x86架构下函数参数怎么传递的,之前只是听别人说过通过寄存器,但是怎么传,什么顺序都没有仔细研究过,也没有实际测试过,因此就想着用实践来检验一下咯。

传参顺序

在32位和64位机器上,寄存器名称不同,64位机器为rxx,32位机器为exx。传参顺序如下,

64位系统有16个寄存器,32位系统只有8个。e开头的寄存器命名依然可以直接运用于相应寄存器的低32位。而剩下的寄存器名则是从r8 - r15,其低位分别用d,w,b指定长度。

测试程序

我们通过简单的程序编译后,使用gdb反汇编看下参数传入是否和上面描述的相符合。

先看看32位程序是怎么传递参数的,

#include <stdio.h>

static int test32(int arg1, int arg2, int arg3, int arg4,int arg5,

                int arg6, int arg7, int arg8)

{

        return 0;

}

int main(void)

{

        test32(1, 2, 3, 4, 5, 6, 7, 8);

        return 0;

}

将函数入参设置成8个,使用gdb反汇编观察参数具体传递情况。

[root@CentOS-7-2 /home/register]# gcc -g -m32 test.c -o test

[root@CentOS-7-2 /home/register]# gdb --quiet

(gdb) file test

Reading symbols from /home/register/test...done.

(gdb) disassemble /m main

Dump of assembler code for function main:

10 {

  0x080483fa <+0>: push  %ebp

  0x080483fb <+1>: mov    %esp,%ebp

  0x080483fd <+3>: sub    $0x20,%esp

11 test32(1, 2, 3, 4, 5, 6, 7, 8);

  0x08048400 <+6>: movl  $0x8,0x1c(%esp)

  0x08048408 <+14>: movl  $0x7,0x18(%esp)

  0x08048410 <+22>: movl  $0x6,0x14(%esp)

  0x08048418 <+30>: movl  $0x5,0x10(%esp)

  0x08048420 <+38>: movl  $0x4,0xc(%esp)

  0x08048428 <+46>: movl  $0x3,0x8(%esp)

  0x08048430 <+54>: movl  $0x2,0x4(%esp)

  0x08048438 <+62>: movl  $0x1,(%esp)

  0x0804843f <+69>: call  0x80483f0 <test32>

12

13 return 0;

  0x08048444 <+74>: mov    $0x0,%eax

14 }

  0x08048449 <+79>: leave 

  0x0804844a <+80>: ret   

End of assembler dump.

由上可见,32位系统中并没有通过寄存器传参,而是直接将参数入栈,而且是按照参数顺序从右向左依次入栈。

现在再来看下64为系统,

#include <stdio.h>

static int test64(long int arg1, long int arg2, long int arg3, long int arg4,

                long int arg5, long int arg6, long int arg7, long int arg8)

{

        return 0;

}

int main(void)

{

        test64(11111111111L, 22222222222L, 33333333333L, 44444444444L,

                55555555555L, 66666666666L, 77777777777L, 88888888888L);

        return 0;

}

这里入参使用long int类型,是因为如果使用int型,编译器会默认使用32位寄存器,即exx寄存器,不直观。

[root@CentOS-7-2 /home/register]# gcc -g -m64 test.c -o test

[root@CentOS-7-2 /home/register]# gdb --quiet

(gdb) file test

Reading symbols from /home/register/test...done.

(gdb) disassemble /m main

Dump of assembler code for function main:

10 {

  0x0000000000400513 <+0>: push  %rbp

  0x0000000000400514 <+1>: mov    %rsp,%rbp

  0x0000000000400517 <+4>: sub    $0x10,%rsp

11 test64(11111111111L, 22222222222L, 33333333333L, 44444444444L,

  0x000000000040051b <+8>: movabs $0x14b230ce38,%rax

  0x0000000000400525 <+18>: mov    %rax,0x8(%rsp)

  0x000000000040052a <+23>: movabs $0x121beab471,%rax

  0x0000000000400534 <+33>: mov    %rax,(%rsp)

  0x0000000000400538 <+37>: movabs $0xf85a49aaa,%r9

  0x0000000000400542 <+47>: movabs $0xcef5e80e3,%r8

  0x000000000040054c <+57>: movabs $0xa5918671c,%rcx

  0x0000000000400556 <+67>: movabs $0x7c2d24d55,%rdx

  0x0000000000400560 <+77>: movabs $0x52c8c338e,%rsi

  0x000000000040056a <+87>: movabs $0x2964619c7,%rdi

  0x0000000000400574 <+97>: callq  0x4004f0 <test64>

12                 55555555555L, 66666666666L, 77777777777L, 88888888888L);

13

14 return 0;

  0x0000000000400579 <+102>: mov    $0x0,%eax

15 }

  0x000000000040057e <+107>: leaveq

  0x000000000040057f <+108>: retq 

End of assembler dump.

为了更直观,我们把64位的入参转换为16进制,

十进制 16进制

11111111111 0x2964619c7

22222222222 0x52c8c338e

33333333333 0x7c2d24d55

从这我们就能看出,参数传递确实是按照rdi、rsi、rdx、rcx、r8、r9的顺序存放第一个参数到第六个参数。对于超出6个参数的入参还是和32位机器一样放入栈中。

相比于参数入栈,通过寄存器传递参数肯定更为高效。

相关文章

  • Linux X86架构参数传递规则

    背景 突然好奇x86架构下函数参数怎么传递的,之前只是听别人说过通过寄存器,但是怎么传,什么顺序都没有仔细研究过,...

  • C或Fortran代码的交叉编译

    在x86架构的Linux操作系统上,编译能直接在arm64架构的Linux上运行的C或fortran程序 安装C交...

  • CPU和GPU

    CPU两大架构x86架构和ARM架构x86架构无法做到ARM架构的低功耗,ARM架构做不到x86架构的高性能。x8...

  • bash shell学习

    Shell 传递参数 参考链接:https://www.runoob.com/linux/linux-shell-...

  • python脚本传递参数

    给python程序传递参数 运行python脚本时有时需要执行实传递参数 在linux下: [root@Test ...

  • note_2_Linux系统组成

    Linux基础: CPU架构:  x86  x64(amd64)  m6800(m68k)  arm  ultra...

  • Linux(1)-CPU

    Linux的CPU Linux的CPU主要是已X86和ARM两个主阵营。 CPU的架构 CPU的指令集:复杂指令集...

  • Ubuntu学习笔记-安装与使用

    Ubuntu 是基于Debian GNU/Linux,支持x86、amd64(即x64)和 ppc架构,由全球化...

  • ubuntu

    介绍 Ubuntu 是基于Debian GNU/Linux,支持x86、amd64(即x64)和ppc架构,与De...

  • Linux内核参数、进程状态

    1、列举常见的内核参数以及参数的意义 Linux内核参数,可以理解为Linux内核在运行过程中,通过传递特定的变量...

网友评论

      本文标题:Linux X86架构参数传递规则

      本文链接:https://www.haomeiwen.com/subject/rksmoqtx.html