汇编:函数以及函数参数传递

汇编语言中的函数(或过程)是指一段可以被调用和执行的代码块;它们用于组织和重用代码,并使程序结构更加清晰;由于汇编语言没有高层次语言的语法糖,编写和调用函数涉及直接的堆栈操作和寄存器管理;以下详细介绍汇编函数的定义、调用、参数传递、返回值处理及一些最佳实践。

汇编语言中的函数调用和高层语言类似,但需要手动处理参数传递、堆栈管理和返回值。

函数的定义

函数在汇编中被定义为一个带有标签的代码块,通常使用 procendp 关键字来定义函数的开始和结束。

my_function proc
    ; 函数体
my_function endp
示例:计算两个整数的和
assume cs:code
​
code segment
    //函数
    readd proc    
        add si,di
        mov ax,si
    ret
    readd endp
​
start:
    mov si,5 
    mov di,6
    
    //函数调用
    call readd
    
    //终止程序并返回dos
    mov ax,4c00h
    int 21h
code ends
end start

这段汇编代码展示了一个简单的程序,其中包含一个名为 readd 的函数,用于将两个寄存器 SIDI 中的值相加,并将结果存储在 AX 寄存器中。然后在程序的开始部分调用该函数,最后终止程序。

start:为程序的入口点,mov si, 5:将立即数 5 存储到 SI 寄存器中;mov di, 6:将立即数 6 存储到 DI 寄存器中;call readd:调用 readd 函数;调用 readd 函数后,SI 中的值变为 11(16进制B),并且 AX 也将包含 B

上述函数是通过寄存器传递参数;在这个示例中,参数 56 被分别存储在寄存器 SIDI 中,然后调用 readd 函数进行处理。

start:
    mov si,5        ; 将 5 存储到 SI 寄存器中
    mov di,6        ; 将 6 存储到 DI 寄存器中
    call readd      ; 调用 readd 函数

通过寄存器传递参数虽然有速度快、效率高的优点,但是由于寄存器数量有限,只适合参数数量较少的情况。

堆栈传参

堆栈传参相对于寄存器传参是一个更通用和灵活的方式,尤其是在需要传递大量参数、处理复杂调用关系或编写递归函数时可以使用这种传参方式。

1.堆栈的基本结构

要了解堆栈传参首先我们需要理解堆栈帧(stack frame)的结构及其在函数调用中的变化;堆栈是一个后进先出(LIFO)数据结构,用于存储函数调用的返回地址、局部变量、参数等;当一个函数被调用时,会创建一个新的堆栈帧,用于存储该函数的局部变量和传递的参数。堆栈帧通常包括以下内容:

调用函数的返回地址
保存的基指针(BP)
函数参数
局部变量

下面是一个简单的堆栈帧结构示意图:

(高地址)High Address、
  +----------------+
  |   局部变量1     |
  +----------------+
  |   局部变量2     |
  +----------------+
  |   ...          |
  +----------------+
  |   参数1         |
  +----------------+
  |   参数2         |
  +----------------+
  |   参数3         |
  +----------------+
  |   ...          |
  +----------------+
  |   函数的返回地址 |  <- 堆栈顶 (SP)
  +----------------+
  |   保存的基指针   |  <- 当前基指针 (BP)
  +----------------+
(低地址)Low Address
​

堆栈从高地址向低地址增长,SP 指向堆栈顶部,BP 用于定位局部变量和参数的位置。

以下是一个简单的堆栈传参示例:

assume cs:code
​
code segment
    add_numbers proc
        push bp          
        mov bp, sp        
        mov ax, [bp+4]    //参数取出 
        add ax, [bp+6]   //结果存放在ax中
        pop bp          
        ret
    add_numbers endp
​
start:
    mov ax,10
    mov bx,5
    //参数传入
    push ax         ; 将ax寄存器中的值压入栈中
    push bx         ; 将bx寄存器中的值压入栈中
    call add_numbers     ;函数调用
    add sp, 4     
    mov ax, 4C00h
    int 21h
code ends
end start

add_numbers procadd_numbers endp:定义了一个名为add_numbers的过程,该过程用于计算两个数的和。

push bp:保存当前函数调用前的基址指针值。

保存当前函数调用前的基址指针值通常是为了确保在函数执行期间能够正确访问调用该函数的上一级函数的栈帧信息。这是因为函数调用时,会产生一个新的栈帧,新的栈帧通常需要访问上一级函数的栈帧信息,比如参数、局部变量和返回地址等。

mov bp, sp:将栈顶指针赋值给基址指针,以便访问函数参数和局部变量。

mov ax, [bp+4]:将第一个参数(位于偏移量为4的位置)加载到寄存器ax中。

add ax, [bp+6]:将第二个参数(位于偏移量为6的位置)加到寄存器ax中。

pop bp:恢复基址指针的原始值。

ret:函数返回。

start:程序的入口点。

mov ax,10:将常数10加载到寄存器ax中。

mov bx,5:将常数5加载到寄存器bx中。

push axpush bx:将axbx中的值分别推送到堆栈中,作为add_numbers函数的参数。

call add_numbers:调用add_numbers函数。

add sp, 4:将堆栈指针移动4个字节,以清除函数调用时推送的参数。

mov ax, 4C00h:将退出程序的DOS功能号加载到寄存器ax中。

int 21h:调用DOS中断,终止程序。

解释了上述的汇编程序的后,我们将目光聚焦到函数参数传递中。
2. 堆栈帧的创建和销毁

此处补充:参数的压栈顺序是由调用约定(calling convention)决定的。在一些常见的调用约定中,如 cdecl、stdcall 等,参数的压栈顺序一般是从右往左的,即先压入的参数在内存中的地址更高,后压入的参数在内存中的地址更低。

假设我们有一个调用 add_numbers 函数的过程,如下所示:

start:
    mov ax,10
    mov bx,5
    push ax         ; 将ax寄存器中的值压入栈中
    push bx          ; 将bx寄存器中的值压入栈中
    call add_numbers ; 调用 add_numbers 函数
    add sp, 4        ; 清理堆栈

函数调用前,堆栈帧的图示

函数调用前堆栈的内容(从高地址到低地址):

high
|-------------|
| 参数 10      |
|-------------| 
| 参数 5       |<-- SP (堆栈指针)
|-------------|
low

执行call add_numbers指令后,即函数调用后,堆栈帧的图示:

|-------------|
| 参数 10      |
|-------------|
| 参数 5       |
|-------------|
| 返回地址      | <-- SP
|-------------|

此时我们转入函数代码中;

函数 add_numbers 的代码
add_numbers proc
    push bp           
    mov bp, sp        
    mov ax, [bp+4]    
    add ax, [bp+6]   
    pop bp            
    ret
add_numbers endp

执行 push bp 指令时,堆栈变化:

|-------------|
| 参数 10      |
|-------------|
| 参数 5       |
|-------------|
| BP 的旧值    |
|-------------|
| 返回地址     | <-- SP
|-------------|

执行 mov bp, sp 指令时,BP 指向 SP

|-------------|
| 参数 10      |
|-------------|
| 参数 5       |
|-------------|
| 返回地址     |
|-------------|
| BP 的旧值    | <-- BP, SP
|-------------|
获取参数的过程:

在计算机体系结构中,堆栈单元的大小通常由体系结构和编译器的约定确定。在x86架构中,包括16位、32位和64位模式,堆栈单元的大小通常是以字节为单位来计算的。

以下是几种常见情况下堆栈单元大小的概述:

①16位模式:在16位模式下,堆栈单元大小通常为2个字节。这意味着每个压入堆栈的元素都占用2个字节的空间。
这种模式下,CPU指令使用基于16位的地址和数据操作。
​
②32位模式:在32位模式下,堆栈单元大小通常为4个字节。每个压入堆栈的元素占用4个字节的空间。
这种模式下,CPU指令使用32位的地址和数据操作。
​
③64位模式:在64位模式下,堆栈单元大小通常为8个字节。每个压入堆栈的元素占用8个字节的空间。
这种模式下,CPU指令使用64位的地址和数据操作。

16位汇编函数获取第一个参数

    指令:mov ax, [bp+4]BP 指向 BP 的旧值,[BP+4] 即为第一个参数的位置(参数 5)。

16位汇编函数获取第二个参数

    指令:add ax, [bp+6]

  BP 指向 BP 的旧值,[BP+6] 即为第二个参数的位置(参数 10)。

BP+4表示相对于基址寄存器(Base Pointer,通常是BP)的偏移地址,即BP中的地址加上4(字节)为第一个参数,BP中的地址+6(字节)获得第二个参数;

至此函数参数传递/调用完毕。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于 N-Gram 文本分类的语言检测器(附详细实现源码)

基于 N-Gram 文本分类的语言检测器 文本分类是文档处理的一项基本任务&#xff0c;可以自动处理大量的电子文档流。处理某些类别文档的一个困难是存在不同类型的文本错误&#xff0c;例如电子邮件中的拼写和语法错误&#xff0c;以及通过 OCR 处理的文档中的字符识别错误。文本…

NebulaGraph

文章目录 关于 NebulaGraph客户端支持安装 NebulaGraph关于 nGQLnGQL 可以做什么2500 条 nGQL 示例原生 nGQL 和 openCypher 的关系 Backup&Restore功能 导入导出导入工具导出工具 NebulaGraph ImporterNebulaGraph ExchangeNebulaGraph Spark ConnectorNebulaGraph Flink …

2024-5-24 石群电路-15

2024-5-24&#xff0c;星期五&#xff0c;22:15&#xff0c;天气&#xff1a;晴&#xff0c;心情&#xff1a;晴。今天最后一天上班&#xff0c;终于要放返校假啦&#xff0c;开心&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;不过放假也不能耽误…

青少年 CTF 练习平台:Misc(一)

前言 当然&#xff0c;我可以更详细地介绍一下青少年CTF练习平台。 青少年CTF练习平台是一个专为青少年设计的网络安全竞赛和训练平台。该平台由思而听&#xff08;山东&#xff09;网络科技有限公司与克拉玛依市思而听网络科技有限公司共同建设&#xff0c;自2018年创建以来…

[笔试训练](三十二)094:素数回文095:活动安排096:合唱团

目录 094:素数回文 095:活动安排 096:合唱团 094:素数回文 题目链接:素数回文_牛客题霸_牛客网 (nowcoder.com) 题目&#xff1a; 题解&#xff1a; 模拟题&#xff1a; 1.构造回文数 2.检测是否为素数 #include <iostream> #include <string> #include <c…

8个实用网站和软件,收藏起来一定不后悔~

整理了8个日常生活中经常能用得到的网站和软件&#xff0c;收藏起来一定不会后悔~ 1.ZLibrary zh.zlibrary-be.se/这个网站收录了超千万的书籍和文章资源&#xff0c;国内外的各种电子书资源都可以在这里搜索&#xff0c;98%以上都可以在网站内找到&#xff0c;并且支持免费下…

「51媒体」广西媒体资源,南宁活动媒体邀约

传媒如春雨&#xff0c;润物细无声&#xff0c;大家好&#xff0c;我是51媒体网胡老师。 广西地区拥有丰富的媒体资源&#xff0c;在广西做活动&#xff0c;参加展览可以邀请他们到场采访报道。 央媒驻站&#xff1a;广西新华 广西人民 广西光明 广西央广 广西国际在线 广西中…

在Spring Boot项目中通过自定义注解实现多数据源以及主备数据库切换

在现代的企业应用开发中&#xff0c;使用多数据源是一个常见的需求。尤其在关键应用中&#xff0c;设置主备数据库可以提高系统的可靠性和可用性。在这篇博客中&#xff0c;我将展示如何在Spring Boot项目中通过自定义注解实现多数据源以及主备数据库切换。 在此说明&#xff…

ICLR 2024现场精彩回顾 机器学习大牛们的“踩高跷秀”嗨翻全场

会议之眼 快讯 2024年5月7-11日&#xff0c;第12届ICLR(International Conference on Learning Representations)即国际学习表征会议已经在奥地利维也纳展览中心圆满结束&#xff01;国际学习表征会议&#xff08;ICLR&#xff09;作为机器学习领域的顶级会议之一&#xff0c;…

开源软件 | 一文彻底搞懂许可证的定义、起源、分类及八大主流许可证,让你选型不再头疼

为什么开源软件会存在许可证&#xff0c;许可证的起源与产生目的是为了解决什么问题&#xff1f;许可证的定义又是怎样的&#xff1f;什么是Copyleft&#xff0c;与Copyright有何区别&#xff1f;开源软件常见的许可证有哪些&#xff1f;这些许可证都有什么特点&#xff1f;接下…

C++中获取int最大与最小值(补)

上文中&#xff0c;我们学习了C中获取int最大与最小值的两种方法&#xff1a;C库和移位运算&#xff0c;这篇文章将解决在移位运算中遇到的各种报错&#xff0c;并提出一种新的生成int最值的方法 上文链接&#xff1a;http://t.csdnimg.cn/cn7Ad 移位运算取最值常见报错 Dev…

【Qt】修改QToolButton图标颜色

1. 目的 修改QToolButton的图标颜色&#xff0c;单一颜色&#xff0c;效果类似于Qt Creator左边选项卡。 2. 代码 QIcon MainWindow::setIconColor(QIcon icon, QColor color) {QPixmap pixmap icon.pixmap(QSize(64,64));QPainter painter(&pixmap);painter.setCompo…

Isaac Sim仿真平台学习(1)认识Isaac Sim

0.前言 上一个教程中我们下载好了Isaac Sim&#xff0c;这一章我们将来简单了解一下Isaac Sim平台。 isaac Sim仿真平台安装-CSDN博客 1.Isaac Sim是啥&#xff1f; What Is Isaac Sim? — Omniverse IsaacSim latest documentation Isaac Sim是NVDIA Omniverse平台的机器…

Window GDI+ API有BUG?GetBounds测不准?

文章目录 GraphicsPath的GetBounds测不准&#xff1f;方法一&#xff1a;GetBounds ()实战 方法二&#xff1a;GetBounds(Matrix)实战 GraphicsPath的GetBounds测不准?实战 .NET 版本的问题&#xff1f;C也一样&#xff0c;不是.NET的问题怀疑人生MiterLimit惹得祸完美结果结束…

深入解析力扣161题:相隔为 1 的编辑距离(逐字符比较与动态规划详解)

❤️❤️❤️ 欢迎来到我的博客。希望您能在这里找到既有价值又有趣的内容&#xff0c;和我一起探索、学习和成长。欢迎评论区畅所欲言、享受知识的乐趣&#xff01; 推荐&#xff1a;数据分析螺丝钉的首页 格物致知 终身学习 期待您的关注 导航&#xff1a; LeetCode解锁100…

Zabbix实现7x24小时架构监控

上篇&#xff1a;https://blog.csdn.net/Lzcsfg/article/details/138774511 文章目录 Zabbix功能介绍Zabbix平台选择安装Zabbix监控端部署MySQL数据库Zabbix参数介绍登录Zabbix WEBWEB界面概览修改WEB界面语言添加被控主机导入监控模板主机绑定模板查看主机状态查看监控数据解…

python实现对应分析的随笔记

文档来源&#xff1a; Correspondence analysis 1 对应分析 参考&#xff1a; SPSS&#xff08;十二&#xff09;SPSS对应分析&#xff08;图文数据集&#xff09;案例6&#xff1a;SPSS–对应分析10 对应分析 对应分析的实质&#xff08;理论很复杂&#xff0c;但是结果很明…

创新工具|AI革新内容营销:策略、工具与实施指南

探索如何利用人工智能&#xff08;AI&#xff09;提升内容营销策略&#xff0c;从SEO优化到个性化推荐。本指南详细介绍了11款顶尖AI工具&#xff0c;旨在帮助中国的中高级职场人士、创业家及创新精英高效地策划和生成引人入胜的内容&#xff0c;同时确保内容的专业性、权威性和…

靶机hackNos Os-Bytesec练习报告

hackNos: Os-Bytesec靶机练习实践报告 下载地址*&#x1f617; https://drive.google.com/open?id1yBuih2CsBx45oTUDpFr4JldrzkaOTTeZ https://download.vulnhub.com/hacknos/Os-ByteSec.ova https://download.vulnhub.com/hacknos/Os-ByteSec.ova.torrent ( Magnet) …

爬虫基础1

一、爬虫的基本概念 1.什么是爬虫&#xff1f; 请求网站并提取数据的自动化程序 2.爬虫的分类 2.1 通用爬虫&#xff08;大而全&#xff09; 功能强大&#xff0c;采集面广&#xff0c;通常用于搜索引擎&#xff1a;百度&#xff0c;360&#xff0c;谷歌 2.2 聚焦爬虫&#x…