ARM assembly: lesson 11

news2024/11/25 8:23:40

在之前,我们提到,当函数的参数小于等于4个时,我们会把它存放于寄存器中,但是如果函数参数大于4个,我们就需要通过stack去进行参数的存储,这毫无疑问,将增加代码操作的复杂性,因为我们需要对于栈利用stack pointer进行控制。

代码回顾

我们回到上次讲到的代码,实现一个加法。但是,如果需要进行6个参数的加法,那么流程会更加复杂。(R0 - R3用于存放前四个参数)

.global _start
_start:
	
	mov r0, #1 //arg1
	mov r1, #2 //arg2

    push {r0, r1}
	bl add_numbers
	mov r2,r0
	pop {r0,r1}
	
add_numbers:
	add r0, r0, r1
	bx lr
	

代码实现

接下来,我们来一步步实现

1. 传入参数

我们将前四个参数分别传入R0 - R3寄存器,因为涉及到function call,所以我们在LR中备份函数调用后需要返回的地址。接下来,我们在栈中预留8byte的空间,用于存放2个数字。通过str指令,我们可以将r4中的数值存放到sp所对应的地址中。

push {lr}
// save the link register,
// so my program knows where to jump back to.

mov r0, #1
mov r1, #2
mov r2, #3
mov r3, #4

//allocate space on the stack to store each variable
//In ARMv7, integer values are 4 bytes long
sub sp, sp, #8
mov r4, #6
str r4, [sp]
mov r4, #5
str r4, [sp, #4]

下图可见,在上述代码的一连串操作后,栈中存放了两个数字以及link register的地址。

2. 函数调用

在step into 函数中,我们需要基于栈和寄存器中的信息,进行加法。然后,基于lr的信息,我们回到了函数被调用的下一条指令。

add_numbers:
    add r0, r0, r1
    add r0, r0, r2
    add r0, r0, r3
    ldr r4, [sp, #4]
    add r0, r0, r4
    ldr r4, [sp]
    add r0, r0, r4

    bx lr

3. 恢复状态

在调用完add_numbers label后,我们需要更新栈,并回到被调用前的状态。

bl add_numbers
mov r2, r0
//reset the stack pointer
add sp, sp, #8
pop {lr}
//sp from -4 to 0
   

The stack grows downward in memory. Subtract from the stack pointer to allocate space for new values.

.global _start
_start:
	
	push {lr}
	mov r0, #1 //arg1
	mov r1, #2 //arg2
	mov r2, #3
	mov r3, #4
	//allocate space on the stack
	sub sp, sp, #8
	mov	r4,	#6
	str r4, [sp]
	mov r4, #5
	str	r4,	[sp, #4]
	
	bl add_numbers
	mov r2,r0
	add	sp,	sp,	#8
	pop {lr}
	
add_numbers:
	add r0, r0, r1
	add	r0,	r0,	r2
	add	r0,	r0,	r3
	ldr	r4,	[sp, #4]
	add	r0,	r0,	r4
	ldr	r4,	[sp]
	add	r0,	r0,	r4
	
	bx lr
	

TakeAway

STR

用于将寄存器中的数据存入memory中。

    STR R0, [R1]      // Store the value in R0 into the memory address in R1

BL

Function Calls: BL is primarily used for calling functions. It allows for both simple function calls and nested or recursive calls.

Return Address Storage: The address of the instruction following the BL is stored in the link register (LR). This allows the called function to return control to the caller.

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

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

相关文章

国外透明代理IP解析:匿名性的全貌

网络世界中,透明代理IP是一个广受关注的话题。究竟什么国外透明代理IP?以及它的匿名性如何?本文将深入解析透明代理IP的定义及其匿名性,为您呈现一个清晰的认识。 1. 概念 透明代理IP是指在进行网络请求时,客户端&am…

(数据结构与算法)哈希表

哈希表把他当成一个key-values表

鸿蒙harmonyos next flutter混合开发之开发plugin(获取操作系统版本号)

创建Plugin为my_plugin flutter create --org com.example --templateplugin --platformsandroid,ios,ohos my_plugin 创建Application为my_application flutter create --org com.example my_application flutter_application引用flutter_plugin,在pubspec.yam…

梯度下降学习

前言:初步学习梯度下降, 不断根据梯度修改我们的参数,经过多次轮次得到使得我们损失函数最小的时候参数,后续我们可以通过类似的道理,更新我们的参数 假设我们的损失函数是 y x 1 2 x 2 2 y x1^2 x2^2 yx12x22,我…

什么是 HTTP Get + Preflight 请求

当在 Chrome 开发者工具的 Network 面板中看到 GET Preflight 的 HTTP 请求方法时,意味着该请求涉及跨域资源共享 (CORS),并且该请求被预检了。理解这种请求的背景,主要在于 CORS 的工作机制和现代浏览器对安全性的管理。 下面是在 Chrome …

常用排序算法(下)

目录 2.5 冒泡排序 2.6 快速排序 2.6 1 快速排序思路 详细步骤 2.6 2 快速排序递归实现 2.6 3快速排序非递归: 快排非递归的优势 非递归思路 1. 初始化栈 2. 将整个数组的起始和结束索引入栈 3. 循环处理栈中的子数组边界 4. 单趟排序 5. 处理分区后的子…

Linux驱动开发(速记版)--热插拔

第九十六章 热插拔简介 热插拔是指在设备运行时安全地插入或拔出硬件,无需关闭或重启系统。 它提供了方便性和灵活性,允许快速更换或添加硬件而无需中断任务。 以下是一些应用场景及支持热插拔所需的条件: 应用场景: USB设备&…

python中,try-except捕获异常的意义(通过ai智库学习)

python中,不但可以用try-except捕获异常, 还可以自定义异常提示字符串,更可以自定义捕获异常后的处置。 (笔记模板由python脚本于2024年10月03日 06:47:06创建,本篇笔记适合喜欢研究python的coder翻阅) 【学习的细节是欢悦的历程】…

交叠型双重差分法

交叠型双重差分法(Staggered Difference-in-Differences, Staggered DiD)是一种扩展的双重差分(Difference-in-Differences, DiD)方法,用于处理多个时间点的政策干预或处理组(treatment group)并…

每日读则推(四)

Whats this...? | An invitation letter n.邀请函 n.邀请(invite v.邀请) Can a tool grasp the meaning in a song? v. 握紧,理解 n.紧握,理解(力) Can it feel the melody, where emotions belong? …

C++ union的运用

// // Created by 徐昌真 on 2024/10/5. // #include <iostream> #include <cstring> using namespace std;//定义一个结构体(类) struct Info{char _name[20];int _role; //老师是0 同学是1union { //用union存放score和course 节省内存int score;char course[2…

全球十大独角兽(完整榜单),你猜中国占几席?

全球十大独角兽 10月3日&#xff0c;OpenAI 宣布已完成 66 亿美元融资&#xff0c;估值达 1570 亿美元&#xff0c;成为全球第三的独角兽。 给新来的读者重温一下"独角兽"的定义&#xff1a;估值超过10亿美元的未上市企业。 你可能会好奇&#xff0c;OpenAI 是第三&a…

Linux·进程概念(下)

1. 进程优先级 优先级就是获得某种资源的先后顺序&#xff0c;因为CPU资源是有限的&#xff0c;因此各个进程之间要去争取CPU的资源。 那么针对Linux操作系统下的PCB中&#xff0c;也就是task_struct结构体中&#xff0c;使用了int类型的变量记录了每个进程的优先级属性&#x…

WIFI网速不够是不是光猫的“路由模式”和“桥接模式”配置错了?

光猫&#xff08;光纤调制解调器&#xff09;是一种用于将光纤信号转换为数字信号的设备&#xff0c;通常用于家庭或企业网络中。光猫可以在不同的工作模式下运行&#xff0c;其中最常见的两种模式是“路由模式”和“桥接模式”。以下是这两种模式的详细解释及其优缺点。 一、路…

python实现单例模式的常用三种方法-基于__new__/使用装饰器以及Python中的值类型、引用类型以及类的静态变量、读取进程和线程ID

一、python实现单例模式的常用三种方法-基于__new__,使用装饰器 涉及到类的使用就会有类的实例化&#xff0c;就会有类单例实现的需求&#xff0c;因为重复实例化会浪费资源。python中的单例模式与别的语言相比&#xff0c;单例实现的方法更丰富。虽然python实现单例的模式的方…

MobaXterm使用

Linux连接工具MobaXterm详细使用教程-CSDN博客

Elasticsearch学习笔记(五)Elastic stack安全配置二

一、手动配置http层SSL 通过前面的配置&#xff0c;我们为集群传输层手动配置了TLS&#xff0c;集群内部节点之间的通信使用手动配置的证书进行加密&#xff0c;但是集群与外部客户端的http层目前还是使用的自动配置&#xff0c;集群中HTTP的通信目前仍然使用自动生成的证书ht…

【韩顺平Java笔记】第7章:面向对象编程(基础部分)【227-261】

文章目录 227. 重载介绍228. 重载快速入门229. 重载使用细节230. 重载课堂练习1231. 232. 重载课堂练习2,3233. 可变参数使用233.1 基本概念233.2 基本语法233.3 快速入门案例 234. 可变参数细节235. 可变参数练习236. 作用域基本使用237. 作用域使用细节1238. 作用域使用细节2…

Docker安装部署和常用命令

Docker 是一种开源的平台&#xff0c;旨在帮助开发者和运维人员更轻松地创建、部署和运行应用程序。通过将应用程序及其依赖项打包到一个名为容器的标准化单位中&#xff0c;Docker 提供了一种轻量级的虚拟化解决方案。与传统虚拟机相比&#xff0c;Docker 容器可以在同一主机上…

GoogleNet原理与实战

在2014年的ImageNet图像识别挑战赛中&#xff0c;一个名叫GoogLeNet 的网络架构大放异彩。以前流行的网络使用小到11&#xff0c;大到77的卷积核。本文的一个观点是&#xff0c;有时使用不同大小的卷积核组合是有利的。 回到他那个图里面你会发现,这里的一个通过我们最大的池化…