Linux X86架构参数传递规则

背景

突然好奇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位机器一样放入栈中。

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

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,186评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,858评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,620评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,888评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,009评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,149评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,204评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,956评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,385评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,698评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,863评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,544评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,185评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,899评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,141评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,684评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,750评论 2 351

推荐阅读更多精彩内容

  • Exercise 3 方法:打开终端运行make qemu-gdb,再打开另一个终端运行make gdb,通过b ...
    找不到工作阅读 10,057评论 0 6
  • 1.地址总线,数据总线,控制总线在哪里,它们有什么作用?答:它们都是cpu连接外部组件的线路。地址总线:地址总线A...
    MagicalGuy阅读 1,440评论 0 1
  • 作者: liigo原文链接: http://blog.csdn.net/liigo/archive/2006/01...
    wuqingyi阅读 1,815评论 0 4
  • 指针和引用形式上很好区别,但是他们似乎有相同的功能,都能够直接引用对象,对其进行直接的操作。但是什么时候使用指针?...
    代码人生ll阅读 417评论 0 0
  • 计算机系统漫游 代码从文本到可执行文件的过程(c语言示例):预处理阶段,处理 #inlcude , #defin...
    willdimagine阅读 3,573评论 0 5