LDMIA R0, {R1, R2, R3, R4}; 和LDMIA R0!, {R1, R2, R3, R4}; 有什么区别
在 ARM 架构的指令集中,LDMIA 是一条加载多个寄存器的指令,其含义为 Load Multiple Increment After,即从内存中加载多个寄存器的值,并且在加载后内存地址递增。
LDMIA R0, {R1, R2, R3, R4}: 这条指令意味着从 R0 指向的内存地址开始,依次将数据加载到 R1, R2, R3, R4,加载完成后,R0 的值不会改变。
LDMIA R0!, {R1, R2, R3, R4}: 结尾的 ! 表示更新基址寄存器。这条指令同样从 R0 指向的内存地址开始,依次将数据加载到 R1, R2, R3, R4,与上一条指令不同的是,执行完这条指令后,R0 的值会更新为最后一个被加载的地址加上 4(即最后一个数据的下一个地址),实质上反映了内存地址的递增。
本质区别在于第二条指令中使用了 !,表示在加载数据到寄存器后,会更新 R0 寄存器的值为新的地址,即指向这一系列操作完成后的下一个内存位置。这种机制通常用于访问连续的内存块,如数组或结构体,且需要在访问过程中更新基址寄存器以指向下一个数据块。
传参数目小于等于4是,直接按顺序用R0, R1, R2, R3传参,超过这个数目就要用栈了,如何用栈传参?a+b+c+d+e用arm指令
在ARM指令集中,当需要传递的参数数量超过4个时,通常会利用堆栈(stack)进行参数传递。以下是一个使用栈传递五个参数(a, b, c, d, e)并计算它们之和的ARM汇编示例:
assembly
.text
.global _start
_start:
// 假设a, b, c, d, e的值分别为1, 2, 3, 4, 5
MOV R0, #1 // a
MOV R1, #2 // b
MOV R2, #3 // c
MOV R3, #4 // d
// 将第5个参数e压入栈中
MOV R4, #5 // e
PUSH {R4} // 将e的值压栈
// 调用函数计算a+b+c+d+e
BL sum_five_numbers
// 结果将在R0中,此处可以添加代码以使用结果
// 终止程序 (在某些环境下有效)
MOV R7, #1
SWI 0
// 函数:计算五个数的和
// 参数:R0=a, R1=b, R2=c, R3=d, 栈顶=e
// 返回值:R0=结果
sum_five_numbers:
// 将R0-R3的值相加,结果存回R0
ADD R0, R0, R1
ADD R0, R0, R2
ADD R0, R0, R3
// 从栈中弹出第5个参数e到R4,并将其加到R0的结果上
POP {R4}
ADD R0, R0, R4
// 返回
BX LR
这个示例展示了如何在ARM汇编语言中通过堆栈传递超过4个的函数参数。首先,前4个参数直接通过寄存器 R0 到 R3 传递,接着额外的参数(这里是第5个参数)通过将值压入堆栈的方式传递。在函数 sum_five_numbers 内部,使用 POP 指令从堆栈中弹出第5个参数,并计算所有参数的总和,最后通过 R0 返回计算结果。
优化等级
arm-none-eabi-gcc -S test.c –O0
arm-none-eabi-gcc -S test.c –O1
发现产生的汇编文件长度变短了
假如现在要操作一个外设寄存器(GPIO),它的地址是
rGPFCON = 0x56000050
我们的每一次读写都必须确确实实地作用在0x56000050这个地址上,而当我们使用了较高的优化等级如-O3时,编译器可能会把对外设寄存器的访问优化掉。
为了解决这类问题,可以使用volatile关键字修饰寄存器地址
#pragma omp parallel for
#pragma omp parallel for 是一种 OpenMP 编译制导语句,用于指示编译器将接下来的 for 循环并行化执行。这意味着循环的迭代将在不同的线程中并行运行,以提高程序的执行效率。这条指令将循环的迭代分配给多个线程,根据系统的可用核心数量和 OpenMP 的调度机制,自动分配循环的迭代给这些线程执行。
#include <stdio.h>
#include <omp.h>
#define N 100
int main() {
int i, sum = 0;
int a[N];
// 初始化数组
for(i = 0; i < N; i++) {
a[i] = i + 1;
}
#pragma omp parallel for reduction(+:sum)
for(i = 0; i < N; i++) {
sum += a[i];
}
printf("Total Sum = %d\n", sum);
return 0;
}