一步步编写操作系统 65 标准调用约定stdcall 汇编实战

因为c语言遵循的调用约定是cdecl,咱们也自然要遵守cdecl约定了。不过为了起到对比的作用,除了介绍cdecl外,也会介绍下stdcall。

既然咱们用的是调用约定是cdecl,那对它的介绍最好让它离下一节的内容近一些,所以先说一下咱们不用的stdcall吧^_^,其实这两个差别就在于由谁来回收栈空间。

stdcall的调用约定意味着:

  1. 调用者将所有参数从右向左入栈;
  2. 被调用者清理参数所占的栈空间;

这两点在上文的表中大家已有所了解,下面咱们将理论实践一下,还是拿上面说过的函数举例:

1 int subtract(int a, int b);	//被调用者
2 int sub = subtract (3,2);		//主调用者

第1行是个函数声明,其实现已经在前面看到了,就是“return a-b”。

第2行进行函数调用,实参分别是3和2。在实际调用中,参数按照从右向左的顺序,参数b会先被压入栈,然后是参数a压入栈。在stdcall调用约定下,这个c代码被编译后的汇编语句是:

主调用者:

;	从右到左将参数入栈
1 push 2				;压入参数b
2 push 3				;压入参数a
3 call subtract		;调用函数subtract

以上是主调函数,现在看下被调函数subtract中做了什么。

被调用者:

1	push ebp			;压入ebp备份。
2	mov ebp,esp		;将esp赋值给ebp,
;用ebp做为基址来访问栈中参数。
3	mov eax,[ebp+0x8]	;偏移8字节处为第1个参数a。
4	add eax,[ebp+0xc]	;偏移0xc字节处是第2个参数b,
;参数a和b相加后存入eax。
5	mov esp,ebp		;为防止中间有入栈操作,用ebp恢复esp。
;本句在此例子中可有可无,属于通用代码。
6	pop ebp				;将ebp恢复
7	ret 8				;数字8表示返回后使esp+8。;函数返回时由被调函数清理了栈中参数。

当执行流进入到subtract后,在它的内部为了用ebp做为基址引用栈中参数,先执行了push ebp来备份ebp,再将栈指针赋给了ebp。目前栈中布局如图

一步步编写操作系统 65  标准调用约定stdcall 汇编实战

 

大家根据上图很容易地看出ebp偏移为8字节是参数a,偏移12字节是参数b。以上代码值得说一下的是ret 8这句。stdcall是被调用者负责清理栈空间,这里的被调用者是函数subtract。也就是说,subtract需要在返回前或返回时完成。在返回前清理栈相对困难一些,清理栈是指将栈顶回退到参数之前。因为返回地址在参数之下,ret指令执行时必须保证当前栈顶是返回地址。所以通常在返回时“顺便”完成。于是ret指令便有了这样的变体,其格式为:

ret 16位立即数

这是允许在返回时顺便再将栈指针esp修改的指令。顺便说一句,由于32位下push指令不是压入字就是压入双字,所以ret的参数必须是偶数。在ret 8执行之前,当前栈顶必须是返回地址,即使没有第5行的代码,当前esp也是等同于ebp,因为之前没有任何push压栈操作,这是编译器为了通用性而加进去的,所以我们在注释中写到,此句可有可无。在经过第6行将栈顶(当前esp指向的内存)弹出到ebp之后,ebp被恢复,此时esp指向了+4字节的位置。即当前栈顶为主调函数的返回地址。结合上图,ret指令将栈顶的数据弹出到寄存器eip后,栈指针esp自加4,由于还有个参数8,所以esp又被加了8,从而跳过了参数a和b,顺利地完成了被调用者清理栈的任务。

stdcall是调用者在栈中压入参数,由被调用者回收栈空间。貌似分工很明确,配合很默契。因为被调用者知道自己需要几个参数,所以知道要回收多少栈空间。 但转念一想,凡事都要自己亲力亲为才放心,调用者压入的参数,万一被调用者忘记回收栈空间该怎么办(这一点由高级语言编译器保证,一般不会,大伙儿放心,本段这么写是为了表述下一种调用约定方式的特点),参数多了栈会溢出的。下面咱们就要介绍这种“亲力亲为”的调用约定,即:调用者自己向栈中压入参数,还是由调用者自己回收栈空间。

好啦,stdcall调用约定就到此为止。大爷再来玩哦。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/439505.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Coursera自动驾驶课程第18讲:The Planning Problem

在第17讲《Coursera自动驾驶课程第17讲:An Autonomous Vehicle State Estimator》 我们学习了如何使用多传感器融合进行自车定位,以及传感器的内外参标定和时间同步,我们还讨论了在实际应用中常遇到的问题。 从本讲开始我们将学习一个新的模…

详解3D物体检测模型:Focal Sparse Convolutional Networks for 3D Object Detection

用于3D目标检测的焦点稀疏卷积神经网络【CVPR2022】【3D检测】本文介绍一篇新的 3D 物体检测模型:Focals Conv,论文收录于 CVPR2022。在 3D 检测任务中,点云或体素数据不均匀地分布在3维空间中,不同位置的数据对物体检测的贡献是不…

地平线:面向规模化量产的自动驾驶感知研发与实践

导读 4月27日,地平线智能驾驶感知研发部负责人苏治中就 《面向规模化量产的自动驾驶感知研发与实践》 这一主题进行了直播讲解。 本次课程内容分为4个部分: 1、地平线自动驾驶环境感知量产实践 2、软硬协同的自动驾驶感知算法设计 3、实现规模化量产的“…

Power BI与Power Query、Power Pivot 是什么关系?

搞不清楚Power BI与Power Query、Power Pivot是什么关系?看这篇文章就够了。 刚开始学习PowerBI的时候,总是能碰到Power Query和Power Pivot这两个词(下文简称为PQ和PP),现在中文里面学习PowerBI的资源本来就不是很多&#xff0c…

地平线:上帝视角与想象力——自动驾驶感知的新范式

导读 3月28日,在「地平线自动驾驶技术专场」上,地平线自动驾驶系统架构师刘景初博士围绕《上帝视角与想象力——自动驾驶感知的新范式 》这一主题进行了直播讲解。 本次课程主要分为以下4个部分: 1、自动驾驶结构演化提出算法新需求 2、软件2…

详解Class类文件的结构(上)

前言 相信搞Java开发的同学都经常会接触到Class类文件,了解了JVM虚拟机之后也会大量接触到class字节码,那么它到底是什么样的文件?内部由什么构成?虚拟机又是如何去识别它的?这篇文章就来学习一下Class类文件的结构。…

Coursera自动驾驶课程第19讲:Mapping for Planning

在第18讲 《Coursera自动驾驶课程第18讲:The Planning Problem》 我们对自动驾驶中的规划问题有了一个全面的了解,理解了规划问题中的约束和目标;同时我们还讨论了如何分层如解决规划问题(任务规划、行为规划、路径规划和速度曲线…

详解Class类文件的结构(下)

本文继续使用上次的Test.class文件,它是由下面单独的一个类文件编译而成的,没有包。 6. 索引(Index) 索引又分类索引、父类索引和接口索引集合,类索引(this_class)和父类索引(super…

自动驾驶开源软件和算法库

1. Carla(自动驾驶开源仿真软件) github:https://github.com/carla-simulator/carladoc:https://carla.readthedocs.io/en/latest/website:http://carla.org/Bounding boxes:https://carla.readthedocs.io/…

Coursera自动驾驶课程第20讲:Mission Planning in Driving Environments

在第19讲《Coursera自动驾驶课程第19讲:Mapping for Planning》 我们学习了自动驾驶中两种环境建图方法:占用网格图(occupancy grid map) 和 高清地图(high-definition road map)。 在本讲中,我…

Java实例化对象过程中的内存分配

问题引入 这里先定义一个很不标准的“书”类,这里为了方便演示就不对类的属性进行封装了。 class Book{String name; //书名double price; //价格public void getInfo(){System.out.println("name:"name";price:"price);} } 在这个类中定义了两个属…

【Python学习】 - sklearn学习 - KNN

前言: 针对一个完整的机器学习框架目前还没有总结出来,所以目前只能总结每一个单独的算法。由于现在研究的重点是算法,所以对于数据的处理,数据的分析和可视化呈现,在现阶段并不进行展示(这样容易陷入纠结…

重读经典:《End-to-End Object Detection with Transformers》

DETR 论文精读【论文精读】这一次朱毅博士给大家精读的论文是 DETR,是目标检测领域里程碑式的一个工作,文章收录于 ECCV20 。DETR 是 Detection Transformer 的缩写,作者使用 Transformer 简化了目标检测流程,不再需要进行 NMS&am…

Execute SQL Task 参数和变量的映射

Execute SQL Task能够执行带参数的SQL查询语句或存储过程(SP),通过SSIS的变量(Variable)对参数赋值。对于不同的Connection Manager,在Task中需要使用不同的符号(Parameter marker)来…

【Python学习】 - 手写数字识别 - python读入mnist数据集的多种方法

写在前面: 其实网上有很多读入mnist数据的代码,但是都是比较麻烦冗长的函数,本篇文章介绍几种不算很麻烦的,借用库函数读入数据的方法。 方法1: 方法2: 方法3:

Coursera自动驾驶课程第21讲:Dynamic Object Interactions

在第20讲《Coursera自动驾驶课程第20讲:Mission Planning in Driving Environments》 我们学习了任务规划中常用的三种图搜索算法:Breadth First Search、Dijkstra 和 A* 搜索。 在本讲中我们将讨论运动规划器中使用的方法,以处理动态物体和…

sql server 数据库忘记sa账户密码/ 无管理员账户解决办法

一、计算机超级管理员账户有数据库的管理员权限 用管理员账户登录数据库,直接修改sa账户密码即可。 二、数据库中没有管理员权限的账户 SQL Server 2005/2008提供了针对该情况的更好的灾难恢复方法,无需侵入master数据库,不会对master数据库…

机器学习编译第1讲:机器学习编译概述

MLC-机器学习编译-第一讲-机器学习编译概述课程主页:https://mlc.ai/summer22-zh/ 文章目录1.0 概述1.1 什么是机器学习编译1.2 为什么学习机器学习编译1.3 机器学习编译的关键要素1.3.1 备注:抽象和实现1.4 总结1.0 概述 机器学习应用程序已经无处不在…

重读经典:《The Craft of Research(1)》

跟读者建立联系【研究的艺术一】这一次李沐博士给大家精读的是一本关于论文写作的书籍。这本书总共包含四个大的章节,本期视频李沐博士介绍的是第一个章节:Research,Researchers,and Readers。 0. 前言 视频开头,李沐…

机器学习编译第2讲:张量程序抽象

02 张量程序抽象 【MLC-机器学习编译中文版】课程主页:https://mlc.ai/summer22-zh/ 文章目录2.1 元张量函数2.2 张量程序抽象2.2.1 张量程序抽象中的其它结构2.3 张量程序变换实践2.3.1 安装相关的包2.3.2 构造张量程序2.3.3 编译与运行2.3.4 张量程序变换2.3.5 通…