如何将以.byte定义的汇编全局数组加载至程序数组?
如何加载汇编定义的全局数组
map到程序数组中 嘿,这个问题我熟!你已经用ARM汇编定义了一个全局的9x9字节数组map,要把它加载到程序里的数组中,分两种常见场景给你讲清楚:
1. 在C语言中访问并加载
因为你用.global声明了map,它是全局可见的符号,所以在C语言里只需要先声明它,就能直接访问或者复制到自己的C数组中。
示例代码
#include <stdio.h> #include <string.h> // 声明汇编中定义的全局数组:9行9列的无符号字节数组 extern unsigned char map[9][9]; int main() { // 定义一个C数组,用来存储加载后的map内容 unsigned char my_program_map[9][9]; // 方法一:批量复制(最简单高效) memcpy(my_program_map, map, sizeof(my_program_map)); // 注:sizeof(my_program_map)刚好是81字节,和你汇编里的数组大小完全匹配 // 方法二:逐个元素复制(适合需要在复制时做修改的场景) for (int row = 0; row < 9; row++) { for (int col = 0; col < 9; col++) { my_program_map[row][col] = map[row][col]; // 这里可以加自定义逻辑,比如对元素做转换 } } // 验证加载结果 printf("map第一行第一列的元素值:%d\n", my_program_map[0][0]); return 0; }
编译的时候记得把汇编文件和C文件一起链接,比如用gcc的话:gcc your_c_file.c your_asm_file.s -o program
2. 在汇编程序中访问并加载
如果是要在ARM汇编里把map加载到另一个数组中,可以通过内存访问指令循环复制,或者用批量加载指令提高效率。
基础循环复制方案(兼容性好)
@ 先定义一个目标数组,预留81字节空间 .global target_map target_map: .space 81 @ 分配81字节的内存,用来存复制后的map @ 定义一个复制函数 .global copy_map_to_target copy_map_to_target: ldr r0, =map @ 把map的起始地址加载到寄存器r0 ldr r1, =target_map @ 把目标数组的起始地址加载到寄存器r1 mov r2, #81 @ 设置要复制的总字节数:9*9=81 copy_loop: ldrb r3, [r0], #1 @ 从map读取1个字节到r3,同时r0地址自增1 strb r3, [r1], #1 @ 把r3的内容写入到target_map,同时r1地址自增1 subs r2, r2, #1 @ 计数器减1 bne copy_loop @ 如果计数器不为0,继续循环 bx lr @ 函数返回
批量加载优化方案(适合支持ARMv7及以上的架构)
如果你的CPU支持批量内存操作,可以一次加载/存储多个字节,提升效率(注意要确保数组地址是4字节对齐的,否则可能触发异常):
.global copy_map_fast copy_map_fast: ldr r0, =map ldr r1, =target_map mov r2, #20 @ 先复制20组4字节(共80字节),剩下1字节单独处理 push {r3-r6} @ 保存会用到的寄存器 batch_copy: ldmia r0!, {r3} @ 从map加载4字节到r3,r0地址自增4 str r3, [r1], #4 @ 把r3的4字节写入到target_map,r1地址自增4 subs r2, r2, #1 bne batch_copy @ 处理最后1字节 ldrb r3, [r0] strb r3, [r1] pop {r3-r6} @ 恢复寄存器 bx lr
不管用哪种方式,只要map是.global声明的,链接器就能正确找到它的内存地址,程序运行时就能正常访问和加载啦。
内容的提问来源于stack exchange,提问作者Ernest T




