C++基础——调用约定分析

C++基础——调用约定分析

调用约定其实自己 Pwn 打了两年半了也是比较了解的,但是还是开个具体的笔记去记录吧。

CPU架构

常见的 CPU 架构有 x86 架构,ARM 架构和 MIPS 架构。不同的架构能执行的机器指令集是不一样的,比如 ARM 下面编译的程序指定是不能在 x86 架构下面去跑的。

x64 为一个简称,全称是 x86-64 架构,也就是 x86 架构下的 64 位版本,多见于我们的 PC,服务器,笔记本等等。

ARM 架构多见于一系列的水果产品和移动端设备。

MIPS 架构多见于路由器、智能设备等等。

处理器发展史

  • 1971年,Intel推出了世界上第一款微处理器4004,它是一个包含了2300个晶体管的4位cPU。
  • 1978年,Intel公司首次生产出16位的微处理器命名为i8086,同时还生产出与之相配合的数学协处理器i8087。
  • 1978年,Intel还推出了具有16位数据通道、内存寻址能力为1MB、最大运行速度8MHz的8086,并根据外设的需求推出了外部总线为8位的8088,从而有了IBM的XT机。
  • 1979年,Intel公司推出了8088芯片,它是第一块成功用于个人电脑的CPU。它仍旧是属于16位微处理器,内含29000个晶体管,时钟频率为4.77MHz,地址总线为20位,寻址范围仅仅是1MB内存。
  • 1981年8088芯片首次用于 IBM PC机中,开创了全新的微机时代。
  • 1982年,Intel推出80286芯片,它比8086和8088都有了飞跃的发展,虽然它仍旧是16位结构,但在CPU的内部集成了13.4万个晶体管,时钟频率由最初的6MHz逐步提高到20MHz。
  • 1985年Intel推出了80386芯片,它X86系列中的第一种32位微处理器,而且制造工艺也有了很大的进步。80386内部内含27.5万个晶体管,时钟频率从 12.5MHz 发展到 33MHz
  • 1989年,80486横空出世,它第一次使品体管集成数达到了120万个,并且在周期内能执行2条指令。
  • 2004,奔四处理器开始占据市场的主流地位。
  • 2006,AMD速龙64*2处理器占主流地位。
  • 2007,年酷睿四核第一次出现在市场上。
  • 2008年,intel诞生720与820处理器。
  • 2010年,I3与I5处理器诞生。
  • 2010年9月,全世界尚未发布的消息,amd六核已经开始供应。
  • 2011年,I7 980X处理器即将退市。
  • 2013年,Intel在 IvyBridge 发布后仅一年发布了新的Haswell架构。
  • 2015年,Intel发布了下一代产品Skylake架构。

汇编语言

计算机只能保存二进制的数据,因此它能直接理解的操作也仅仅是由二进制编码形成的指令,指令通常只能完成很小范围的一个操作,比如加减乘除,取数存数等等。但是二进制的编码不利于人类阅读,因此汇编语言诞生了,汇编语言与机器语言是硬编码,一一对应的一个关系。

汇编代码执行的过程:

16位

在这个位数的处理器下面我们有 8 个通用寄存器——ax,bx,cx,dx,di,si,bp,sp,一个指令指针寄存器——ip还有标志寄存器——flag,段寄存器——CS,SS,DS,ES

32位

对以上寄存器进行扩展(expand),在所有寄存器前面加上 e 变成了 32 位版本的寄存器,段寄存器无变化多了 FS 和 GS

64位

多了 8 个通用寄存器 r8-r15,然后所有的寄存器标识符由 32 位的 e 变为了 r。

函数调用约定

32位

一共有四种:

  • __cdecl:C/C++的基本调用约定,参数从右往左压入栈中,调用者清理栈。
  • __stdcall:win32 api 的调用约定,参数从右往左压入栈中,被调用者平衡栈,在返回的时候会使用 ret x 指令,这个 x 会在我们把返回地址弹出之后给 esp 加上 x 用于平衡栈。
  • __fastcall:快速传参,前两个参数给 ecx 和 edx 寄存器,若有多余,则剩余参数从右往左压入栈中,被调用者清理栈,与 stdcall 类似。
  • __thiscall:对象的传参使用,this 指针给到 ecx 寄存器,其它参数从右往左压入栈中,被调用者清理栈。

如果参数不固定,则调用约定只能是 __cdecl,因为被调用者不能知道自己参数是多少个,只有调用者知道它参数给了几个,因此只能选择调用者清理栈的 __cdecl

64位

只有两种:

  • __cdecl:前六个参数保存在 rdi,rsi,rdx,rcx,r8,r9 中,若参数有多余,其余参数从右往左压入栈中,调用者清栈。
  • __fastcall:前四个参数保存子 rcx,rdx,r8,r9 中,若参数有多余,其余参数从右往左压入栈中,被调用者清栈。
文章目录
  1. 1. CPU架构
    1. 1.1. 处理器发展史
    2. 1.2. 汇编语言
      1. 1.2.1. 16位
      2. 1.2.2. 32位
      3. 1.2.3. 64位
    3. 1.3. 函数调用约定
      1. 1.3.1. 32位
      2. 1.3.2. 64位
|