__cdecl与__stdcall概念中的调用者和被调用者是什么意思?

发布于 2022-08-30 16:14:17 字数 448 浏览 12 评论 0

我只学过C入门,只做过课后习题,最近刚学windows下的C。
但书上第一个程序我就看不懂了

int WINAPI WinMain()

这里的WINAPI我从来没见过这种用法,网上查了下其实是指定__cdecl或__stdcall等这样的函数调用约定,但即使是看了大篇文章后我还是不懂,主要是这些话:

不论__stdcall还是__cdecl函数参数都是从右向左入栈的,并且由调用者完成入栈操作。对于__stdcall方式被调用者自身在函数返回前清空堆栈;而__cdecl则由调用者维护内存堆栈,所以调用者函数生成的汇编代码比前一种方式长。

我想知道上述的调用者/被调用者是人(我自己)还是函数?这些入栈/清空堆栈的操作指的是不是要在申请动态内存后要记得free()掉?不然指的是什么?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

苏璃陌 2022-09-06 16:14:17

你都已经查到 __stdcall这一步了,再往下多查一步不就知道了么。

调用者(caller)和被调用者(callee)都是指函数。入栈清栈指的是函数调用参数传递的方式。清栈职责在caller这边,意思就是:

cfoo(123);

转换成汇编是:

gaspush 123;
call foo;
add $4,%esp;  #将Stack Pointer %esp 加4即是清栈
              #4表示32位下4个字节一个word

如果职责在callee那边,上面最后一行就移到foo中:

gasfoo:
  # do something
  add $4,%esp
  ret

后一种方式一个函数只能接受固定个数的参数,因为编译时就需要确定 add x,%espx到底是几。

哦,对了,这些都是编译器的行为,程序员根本不需要关心。

念﹏祤嫣 2022-09-06 16:14:17

学编程最重要的是了解运行环境、如操作系统、编译器。语言本身并不太重要。
有一个必需掌握的能力就是调试能力,要有汇编级调试能力。有了这个能力,你的问题调试跟踪一下能找到答案了。
很多时候,要提高这种能力,可以通过学习逆向工程获得。
国内看雪学院http://www.pediy.com/是个不错的地方。

娇女薄笑 2022-09-06 16:14:17

WINAPI本身就宏定义,也就是 #define WINAPI __stdcall 当然这个在Mac下面不一样。几乎所有的Win32 API函数都是这种类型。编译后的程序体积小些,名字改编不一样。还有一个明显的特征,比如printf支持变长,而WINAPI的是不支持变长的,因为被调用者不知道传入参数是多少,不懂的如何去清理,所以这里printf得是__cdecl

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文