反汇编分析__stdcall和__cdecl的异同

C++代码如下:
.h头文件

#pragma once

#ifdef DLLTestAPI

#else
#define DLLTestAPI _declspec(dllimport)
#endif

int DLLTestAPI __stdcall add(int, int);

int DLLTestAPI __cdecl subtract(int, int);

.cpp代码文件

#define DLLTestAPI _declspec(dllexport)

#include "Test.h"

int __stdcall add(int a, int b)
{
    return a + b;
}

int __cdecl subtract(int a, int b)
{
    return a - b;
}

可以看到 add方法是使用__stdcall修饰的,而subtract方法是使用__cdecl修饰的。

反汇编后得到的汇编代码如下

add方法:

100115D0    55              PUSH EBP
100115D1    8BEC            MOV EBP,ESP
100115D3    81EC C0000000   SUB ESP,0C0
100115D9    53              PUSH EBX
100115DA    56              PUSH ESI
100115DB    57              PUSH EDI
100115DC    8DBD 40FFFFFF   LEA EDI,DWORD PTR SS:[EBP-C0]
100115E2    B9 30000000     MOV ECX,30
100115E7    B8 CCCCCCCC     MOV EAX,CCCCCCCC
100115EC    F3:AB           REP STOS DWORD PTR ES:[EDI]
100115EE    8B45 08         MOV EAX,DWORD PTR SS:[EBP+8]
100115F1    0345 0C         ADD EAX,DWORD PTR SS:[EBP+C]
100115F4    5F              POP EDI
100115F5    5E              POP ESI
100115F6    5B              POP EBX
100115F7    8BE5            MOV ESP,EBP
100115F9    5D              POP EBP
100115FA    C2 0800         RETN 8

subtract方法:

10011610    55              PUSH EBP
10011611    8BEC            MOV EBP,ESP
10011613    81EC C0000000   SUB ESP,0C0
10011619    53              PUSH EBX
1001161A    56              PUSH ESI
1001161B    57              PUSH EDI
1001161C    8DBD 40FFFFFF   LEA EDI,DWORD PTR SS:[EBP-C0]
10011622    B9 30000000     MOV ECX,30
10011627    B8 CCCCCCCC     MOV EAX,CCCCCCCC
1001162C    F3:AB           REP STOS DWORD PTR ES:[EDI]
1001162E    8B45 08         MOV EAX,DWORD PTR SS:[EBP+8]
10011631    2B45 0C         SUB EAX,DWORD PTR SS:[EBP+C]
10011634    5F              POP EDI
10011635    5E              POP ESI
10011636    5B              POP EBX
10011637    8BE5            MOV ESP,EBP
10011639    5D              POP EBP
1001163A    C3              RETN

大家已经看到了,他们的唯一区别是:
使用__stdcall修饰的add方法,最后的RETN指令的操作数是8,而使用__cdecl修饰的subtract方法,最后的RETN指令没有操作数。

RETN指令的操作数为什么是8呢,原因也很简单,就是add方法有两个int参数,也就是说压栈的时候压入了两个字节,正好8位,RETN 8的意思应该是让栈顶指针ESP向后移动8位。

时间: 2025-01-20 21:41:54

反汇编分析__stdcall和__cdecl的异同的相关文章

关于函数调用方式__stdcall和__cdecl详解_C 语言

关于函数调用方式__stdcall和__cdecl详解 __stdcall __cdecl 两者的相同点与不同点 实例 __stdcall __stdcall的全称是standard call.是C++的标准调用方式. 函数参数的入栈顺序为从右到左入栈.函数返回时使用retn x指令,其中x为调整堆栈的字节数.这种方式叫做自动清栈.即被调用的函数的参数个数是固定的,调用者必须严格按照定义传递参数,一个不多,一个不少. __cdecl __cdecl的全称是C Declaration,即C语言默认

__stdcall 和 __cdecl 的区别浅析_C 语言

1. __cdecl__cdecl 是C Declaration的缩写(declaration,声明),表示C语言默认的函数调用方法:所有参数从右到左依次入栈,由调用者负责把参数压入栈,最后也是由调用者负责清除栈的内容,一般来说,这是 C/C++ 的默认调用函数的规则,MS VC 编译器采用的规则则是这种规则2. __stdcall_stdcall 是StandardCall的缩写,是C++的标准调用方式:所有参数从右到左依次入栈,由调用者负责把参数压入栈,最后由被调用者负责清除栈的内容,Win

WIN98SE硬盘主引导记录代码反汇编分析

硬盘引导记录MBR(Master Boot Record)是指硬盘之0面0道1扇区之内容,PC及其兼容机之ROM BIOS约定在上电及POST自检成功后,将其从硬盘读出,放置在内存0:7C00处,然后转去该地址执行.该段代码负责从代码尾部之4个分区表项中找出可以引导的项,读出其引导记录引导之.     MBR在相当长时间内都保持着1982年IBM设计IBM PC机时的代码原样,直到硬盘容量突破传统BIOS所能支持的最大容量8.4G之时,它才不得不加入新的INT13功能扩展代码,不过主要的功能还是

__cdecl __stdcall 解析

1.如果函数func是__cdecl(默认调用方式),调用时情况如下  int    main()    {    //参数从右到左压栈     push   4     push   3     push   2     push   1     call    func     add    esp   0x10   //调用者恢复堆栈指针esp,4个参数的大小是0x10(4x4)     }    2.如果函数func是__stdcall,调用时情况如下  int    main()   

__stdcall,__cdecl,_cdecl,_stdcall,。__fastcall,_fastcall 区别简介

1.  今天写线程函数时,发现msdn中对ThreadProc的定义有要求:DWORD WINAPI ThreadProc(LPVOID lpParameter);  不解为什么要用WINAPI宏定义,查了后发现下面的定义.于是乎需要区别__stdcall和__cdecl两者的区别: #define CALLBACK __stdcall #define WINAPI __stdcall #define WINAPIV __cdecl #define APIENTRY WINAPI #define

IDA反汇编/反编译静态分析iOS模拟器程序(九)block

在第三节 函数表示与搜索函数 提到block函数和普通的OC函数不同. 反汇编分析前需要理解block的实现原理,故推荐先看看这几篇文章及其所引用的参考资料: Block介绍(一)基础Block介绍(二)内存管理与其他特性block介绍(三)揭开神秘面纱(上)block介绍(四)揭开神秘面纱(下) block函数的命名与上文提到类似.函数内部定义的block会以scope命名,如: @implementation ViewController - (void)later { [self pres

IDA反汇编/反编译静态分析iOS模拟器程序(一)话说IDA

上个月写了一系列文章<xcode反汇编调试iOS模拟器程序>,是使用xcode来动态反汇编分析iOS模拟器程序的.这个系列则是静态分析,用到IDA来做反汇编/反编译.一些概念不会在此重复,遇到时可回读xcode反汇编系列. 之前有提到一些IDA的常识和下载地址,可看 <IDA Pro权威指南>读书笔记,同时这本书也是更深入挖掘IDA的参考书,只不过书里不会提到Objective-C.本系列使用的是Windows IDA 6.1和Mac IDA 6.4. 详细的关于IDA的介绍还是由

gdb反汇编详解C函数底层实现笔记(程序堆栈、内存分配)

以下是在读<深入理解计算机系统>前面的章节"程序的机器级表示"时,自己动手在linux上使用了gdb对一个简单的C程序进行反汇编,通过不懈的努力终于查清楚弄明白了绝大多数的语句.且均以注释的形式列在汇编语句后面.       所有这些注释大概花了整整一天时间,不过还好,感觉对于C程序的机器级实现终于算是有了一个比较透彻的理解,对于以前编译出现的有些bug的原因有了一种原来如此的感慨.感觉这段代码及注释对自己或者大家都可能有用,所以稍作整理放于此:   说明: 反汇编指令使用

一种实现Win32消息处理处理函数的新方法 - 基于Thunk实现的类成员消息处理函数

Windows是一个消息驱动的操作系统,在系统中发生的所有消息均需要通过消息处理过程(或叫窗口过程)进行处理.由于C++给我们在程序设计中带来更多的灵活性(如继承.重载.多态等),所以我们都希望能够使用C++的类来封装Windows中的窗口过程函数,但是Windows规定了窗口过程函数必须定义为一个全局函数,也就是说需要使用面向过程的方法来实现,为了使用面向对象的技术来实现消息处理,我们必须另辟它径.目前我们在网络上见得比较多的方式是使用Thunk将即将传递给窗口过程的第一个参数(HWND hW