专栏首页E条咸鱼x86架构与x64架构在函数于栈中调用过程的不同之处

x86架构与x64架构在函数于栈中调用过程的不同之处

本篇原创作者:Rj45

x86架构与x64架构

1、x86架构 x86架构是intel开发的一种32位的指令集。8个32位通用寄存器 eax,ebx,ecx,edx,ebp,esp,esi,edi

2、x64架构 x64架构是64位的,有16个通用寄存器 rax,rbx,rcx,rdx,rsi,rdi,rsp,rbp,r8,r9,r10,r11,r12,r13,r14,r15

程序

1、代码

2、编译链接

32位:
sudo gcc stack.c -o stack -m32

64位:
sudo gcc stack.c -o stack1

x86架构下函数于栈中调用过程

0804840b <Add>:
 804840b:    55                      push   ebp          //将ebp压入栈
 804840c:    89 e5                   mov    ebp,esp      //将esp压入栈
 804840e:    83 ec 08                sub    esp,0x8      //抬高栈帧
 8048411:    8b 55 08                mov    edx,DWORD PTR [ebp+0x8]  //将[ebp+0x8]压入edx
 8048414:    8b 45 0c                mov    eax,DWORD PTR [ebp+0xc]  //将[ebp+0xc]压入eax
 8048417:    01 d0                   add    eax,edx  //将eax与edx中的内容相加赋给eax
 8048419:    83 ec 08                sub    esp,0x8  //抬高栈帧
 804841c:    50                      push   eax  //将eax压入栈
 804841d:    68 e0 84 04 08          push   0x80484e0    //压入x+y=
 8048422:    e8 b9 fe ff ff          call   80482e0 <printf@plt> //调用printf函数
 8048427:    83 c4 10                add    esp,0x10 //调整栈帧
 804842a:    90                      nop
 804842b:    c9                      leave
 804842c:    c3                      ret

0804842d <main>:
 804842d:    8d 4c 24 04             lea    ecx,[esp+0x4]
 8048431:    83 e4 f0                and    esp,0xfffffff0
 8048434:    ff 71 fc                push   DWORD PTR [ecx-0x4]

 8048437:    55                      push   ebp      //将ebp压入栈
 8048438:    89 e5                   mov    ebp,esp  //将esp压入栈
 804843a:    51                      push   ecx      //将ecx压入栈
 804843b:    83 ec 04                sub    esp,0x4  //抬高栈帧,esp=esp+0x4
 804843e:    83 ec 08                sub    esp,0x8  //抬高栈帧
 8048441:    6a 14                   push   0x14     //压入参数20
 8048443:    6a 0a                   push   0xa      //压入参数10
 8048445:    e8 c1 ff ff ff          call   804840b <Add>    //调用Add函数
 804844a:    83 c4 10                add    esp,0x10 //调整栈帧
 804844d:    b8 00 00 00 00          mov    eax,0x0  //清空eax
 8048452:    8b 4d fc                mov    ecx,DWORD PTR [ebp-0x4]  //将[ebp-0x4]内的数据赋给ecx
 8048455:    c9                      leave           //mov esp,ebp;pop ebp
 8048456:    8d 61 fc                lea    esp,[ecx-0x4]    //取[ecx-0x4]中的数据赋给esp
 8048459:    c3                      ret             //pop eip

 804845a:    66 90                   xchg   ax,ax
 804845c:    66 90                   xchg   ax,ax
 804845e:    66 90                   xchg   ax,ax

x64架构下函数于栈中调用过程

0000000000400526 <Add>:
  400526:    55                      push   rbp          //将rbp压入栈中
  400527:    48 89 e5                mov    rbp,rsp      //将rsp压入栈中
  40052a:    48 83 ec 10             sub    rsp,0x10     //抬高栈帧
  40052e:    89 7d fc                mov    DWORD PTR [rbp-0x4],edi  //将edi的值赋给[rbp-0x4]
  400531:    89 75 f8                mov    DWORD PTR [rbp-0x8],esi  //将rsi的值赋给[rbp-0x10]
  400534:    8b 55 fc                mov    edx,DWORD PTR [rbp-0x4]  //将[rbp-0x4]的值赋给edx
  400537:    8b 45 f8                mov    eax,DWORD PTR [rbp-0x8]  //将[rbp-0x8]的值赋给eax
  40053a:    01 d0                   add    eax,edx                  //eax=eax+edx
  40053c:    89 c6                   mov    esi,eax                  //将eax的值赋给esi
  40053e:    bf 04 06 40 00          mov    edi,0x400604         //将0x400604对应的数据赋给edi
  400543:    b8 00 00 00 00          mov    eax,0x0              //清空eax
  400548:    e8 b3 fe ff ff          call   400400 <printf@plt>  //调用printf函数
  40054d:    90                      nop
  40054e:    c9                      leave
  40054f:    c3                      ret

0000000000400550 <main>:
  400550:    55                      push   rbp          //将rbp压入栈中
  400551:    48 89 e5                mov    rbp,rsp      //将rsp压入栈中
  400554:    48 83 ec 10             sub    rsp,0x10     //抬高栈帧
  400558:    89 7d fc                mov    DWORD PTR [rbp-0x4],edi  //将edi的值赋给[rbp-0x4]
  40055b:    48 89 75 f0             mov    QWORD PTR [rbp-0x10],rsi //将rsi的值赋给[rbp-0x10]
  40055f:    be 14 00 00 00          mov    esi,0x14     //将参数20赋给esi
  400564:    bf 0a 00 00 00          mov    edi,0xa      //将参数10赋给edi
  400569:    e8 b8 ff ff ff          call   400526 <Add> //调用Add函数
  40056e:    b8 00 00 00 00          mov    eax,0x0      //清空eax
  400573:    c9                      leave               //mov esp,ebp;pop ebp
  400574:    c3                      ret                 //pop eip
  400575:    66 2e 0f 1f 84 00 00    nop    WORD PTR cs:[rax+rax*1+0x0]
  40057c:    00 00 00
  40057f:    90                      nop

总结

x86架构与x64架构在函数于栈中调用过程的不同之处在于:x86架构下,函数的参数是直接存放到栈帧中的;而x64架构下,函数的参数是通过寄存器传参进入栈帧的。(当寄存器不够用,才会将参数直接存入栈帧)

本文分享自微信公众号 - E条咸鱼(gh_04d31a502ded),作者:Rj45

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-10-01

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 由一个简单的程序学习常见汇编指令

    一直以来,内心有股焦急焦虑,急冲冲的学习,急冲冲的比赛,没有时间和心思回过头来静心总结。突然之间想安静下来回顾和记录一下pwn的知识点 其实是写web有点累...

    Elapse
  • 简单缓冲区溢出原理

    1、审计:可以看到,程序一开始声明并初始化了key=0x12345678, 并声明了32字节的buf, 然后通过strcpy函数将第一个参数拷贝到buf中, 接...

    Elapse
  • 一条payload发生的事情(来自对报错注入的思考)

    最近在重新整理复现MYSQL注入天书,遇到了一条很有意思的报错注入的payload:

    Elapse
  • 短视频程序,日期选择框前进后退

    yunbaokeji柯基
  • list、dict和set的综合应用:排课系统(3)

    上回说到,我们完成了用来测试排课算法的相关数据的添加,这次我们就来实现排课算法,算法相对来说比较复杂,主要用到的数据结构有 list、dict 以及 set,至...

    不可言诉的深渊
  • 源码分析--dubbo服务端暴露

    服务暴露的入口方法是 ServiceBean 的 onApplicationEvent。onApplicationEvent 是一个事件响应方法,该方法会在收到...

    luozhiyun
  • PHP 判断数组是否为空的5大方法

    本文介绍了PHP开发中遇到的数组问题,这里介绍了判断PHP数组为空的5种方法,有需要的朋友可以借鉴参考一下。 转载自:PHP100 原文地址:http://ww...

    wangxl
  • Uber 四年时间增长近 40 倍,背后架构揭秘

    据报道,Uber 仅在过去4年的时间里,业务就激增了 38 倍。Uber 首席系统架构师 Matt Ranney 在一个非常有趣和详细的访谈《可扩展的 Uber...

    CSDN技术头条
  • 代码浏览工具OpenGrok

    felix
  • LBank余币宝上线秒罄!如何准备抢购第二期?

    北京时间2018年4月24日(周二)晚上20:00,全球排名Top 9的数字资产交易平台LBank开启了第一期余币宝抢购活动,第一期总共上线了6种资产,均在几秒...

    区块链领域

扫码关注云+社区

领取腾讯云代金券