ARM处理器 两个 64 位数相加的汇编程序解析

ARM处理器 两个 64 位数相加的汇编程序解析

				AREA add64, CODE, READONLY
				; 定义一个只读属性的代码段
start 			PROC
				LDR R0, =data1 ; R0 中保存 data1 的首地址
				LDR R1, [R0] 
				; 用寄存器间接寻址方式读数据 1 的高 32 位到 R1
				LDR R2,[R0,#4] 
				; 用寄存器间接寻址方式读数据 1 的低 32 位到 R2
				LDR R0, =data2 ; R0 中保存 data2 的首地址
				LDR R3, [R0] 
				; 用寄存器间接寻址方式读数据 2 的高 32 位到 R3
				LDR R4,[R0,#4] 
				; 用寄存器间接寻址方式读数据 1 的低 32 位到 R4
				ADDS R6,R2,R4 
				; 低 32 位相加,并影响标志位,保存进位
				ADCS R3,R1,R3 ; 高 32 位相加,并使用标志位 C
				MOV R5,R3
				LDR R0.,=0x20000100 ; R0 中保存 0x20000100 的首地址
				STR R5,[R0] ; 保存结果的高位
				STR R6,[R0,#4] ; 保存结果的低位
data1 			DCD 0x12345678,0xFFDDCCBB
data2 			DCD 0x11223344,0xFFDDCCBB
				ENDP

LDR 指令

LDR R0, =data1 ; R0 中保存 data1 的首地址
LDR R1, [R0] ; 用寄存器间接寻址方式读数据 1 的高 32 位到 R1
LDR R2,[R0,#4] ; 用寄存器间接寻址方式读数据 1 的低 32 位到 R2
LDR R0, =data2 ; R0 中保存 data2 的首地址
LDR R3, [R0] ; 用寄存器间接寻址方式读数据 2 的高 32 位到 R3
LDR R4,[R0,#4] ; 用寄存器间接寻址方式读数据 1 的低 32 位到 R4

LDR 指令是 ARM 处理器中的一种数据传输指令,用于将内存中的数据加载到寄存器中。LDR 指令有多种寻址方式,包括立即数寻址、寄存器寻址、变址寻址、基址加变址寻址等。下面是一些 LDR 指令使用多种寻址方式的例子:

  • 立即数寻址:LDR R0, =0x12345678 ; 将立即数 0x12345678 加载到 R0 寄存器中
  • 寄存器寻址:LDR R0, [R1] ; 将 R1 寄存器中的地址所指向的内存单元中的数据加载到 R0 寄存器中
  • 变址寻址:LDR R0, [R1, #4] ; 将 R1 寄存器中的地址加上 4 所得到的地址所指向的内存单元中的数据加载到 R0 寄存器中
  • 基址加变址寻址:LDR R0, [R1, R2] ; 将 R1 寄存器中的地址加上 R2 寄存器中的值所得到的地址所指向的内存单元中的数据加载到 R0 寄存器中

存储数据和地址

ARM 是 32 位的处理器,一次只能完成两个 32 位数据之间的运算。若要实现两个 64 位数相加(如上面汇编代码),关键在于首先完成两个数的低 32 位相加并保存进位,再完成两个数的高 32 位及低 32 位加法进位之间的加法

如果数组中只包含一个64位整数,它的值为0x11223344FFDDCCBB,那么可以这样表示:

data1 			DCD 0x12345678,0xFFDDCCBB

DCD 指令表示定义双字数据,双字(Double word)数据是数据长度为 4 个字(32 位),也就是 4 个字节。

那么可能有人想,为什么不能写成这样:

data1 			DCD 0x12345678FFDDCCBB

**不可以!**这是由于data1是一个64位整数,而ARM是32位的处理器,它最多占据8个字节的存储空间,所以在内存中存储时,需要按照顺序依次存储该整数的高32位和低32位。

!需要重点注意的是:ARM实际上是小端模式存储的,什么意思呢,就是就是高位字节存储在低地址,低位字节存储在高地址,还是觉得抽象吗,那请看下图

在这里插入图片描述

这是在keil中的仿真,0x00000060是程序运行到LDR R0, =data1时,R0里存的值,也就是data1的首地址。

看一下地址和数据对应:

地址      	数据(16进制) 
0x00000060    78
0x00000061    56
0x00000062    34
0x00000063    12
0x00000064    BB
0x00000065    CC
0x00000065    DD
0x00000065    FF

再回过头来看数据data1是什么,汇编代码是怎么写的

data1 		DCD 0x12345678,0xFFDDCCBB

1个地址能储存8位数据,看完上表,大概能理解ARM内存存储方式了吧

细心的人还发现了一个问题

data1 			DCD 0x12345678,0xFFDDCCBB
data2 			DCD 0x11223344,0xFFDDCCBB

为什么这段定义数据的代码在整个代码的最后,而不是像C语言一样,在代码前面就定义数据。

这是因为,在汇编语言中,定义数据段通常会与代码段分开,因为数据段是只读的,而代码段是可执行的。这样做有利于保证程序运行的安全性和稳定性。

通常来说,数据段定义在代码末尾,是因为在程序运行的时候,数据需要被读取和使用,所以先要加载代码段,等到需要使用数据的时候再加载数据段。

而在 C 语言中,数据通常会在程序的开始就被定义,是因为 C 语言中数据的定义通常会涉及到变量的初始化等操作,这些操作需要在程序开始运行之前完成。

ADDS和ADCS

ADDS R6,R2,R4 ; 低 32 位相加,并影响标志位,保存进位
ADCS R3,R1,R3 ; 高 32 位相加,并使用标志位 C
MOV R5,R3

ADDS指令用于执行两个寄存器的加法操作,并将结果存储到第一个寄存器中。如果加法结果产生了进位(Carry),则标志寄存器的进位标志位(C)被设置为1,否则被设置为0。此外,还可以根据结果设置其他标志寄存器的标志位(N、Z、V)。

在这里插入图片描述

ADCS指令和ADDS类似,不同之处在于它还考虑了上一次运算是否产生了进位。具体来说,ADCS指令执行的是两个寄存器的加法操作,同时还加上上一次运算产生的进位(通过标志寄存器的进位标志位C得到)。如果加法结果产生了进位,那么进位标志位C被设置为1,否则被设置为0。ADCS指令执行后,可以根据结果设置标志寄存器的标志位。

而代码中 还使用了MOV R5,R3的原因是,MOV R5, R3 就是将 R3 中保存的高32位结果单独存放到了 R5 中,便于后续的操作。因为 ADCS 指令已经处理好了进位标志位,而在后续的指令中不需要再考虑进位的问题。因此,直接使用 R5 中的结果进行存储即可,不需要再将进位标志位加上。

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值