1471 字
7 分钟
汇编代码初始化数组
初始化数组(存储在RAM中)
方法1:使用DS在RAM中预留空间
ORG 30H ; 从30H开始分配RAM变量
; 未初始化的数组(预留空间)BUFFER: DS 16 ; 预留16字节的缓冲区TEMP_ARRAY: DS 8 ; 预留8字节的温度数组RESULTS: DS 32 ; 预留32字节的结果数组
; 混合定义DATA_AREA:VAR1: DS 1 ; 单个字节变量ARRAY1: DS 10 ; 10字节数组VAR2: DS 1 ; 另一个变量方法2:运行时初始化数组
; 初始化RAM数组的函数INIT_ARRAYS: ; 初始化BUFFER数组为0 MOV R0, #BUFFER ; 数组起始地址 MOV R2, #16 ; 数组长度 CLR A ; A = 0INIT_LOOP1: MOV @R0, A ; 清零数组元素 INC R0 DJNZ R2, INIT_LOOP1
; 初始化TEMP_ARRAY为特定值 MOV R0, #TEMP_ARRAY MOV @R0, #20 ; TEMP_ARRAY[0] = 20 INC R0 MOV @R0, #25 ; TEMP_ARRAY[1] = 25 INC R0 MOV @R0, #30 ; TEMP_ARRAY[2] = 30 ; ... 继续初始化
RET访问常数变量和数组
1. 访问ROM中的常数(使用MOVC)
; 读取SINE_TABLE中的第3个元素READ_SINE_VALUE: MOV DPTR, #SINE_TABLE ; 设置表基址 MOV A, #2 ; 索引2(第3个元素) MOVC A, @A+DPTR ; A = SINE_TABLE[2] = 25 RET
; 读取字符串中的字符READ_MESSAGE_CHAR: MOV DPTR, #MESSAGE ; 字符串地址 MOV R2, #0 ; 字符索引READ_LOOP: MOV A, R2 ; 索引到A MOVC A, @A+DPTR ; 读取字符 JZ END_OF_STRING ; 如果是0,字符串结束 ; 处理字符... INC R2 ; 下一个字符 SJMP READ_LOOPEND_OF_STRING: RET2. 访问RAM中的数组
; 通过索引访问数组元素ACCESS_ARRAY_ELEMENT: ; 参数:R7 = 数组索引 ; 返回:A = 数组元素
MOV A, R7 ; 索引到A ADD A, #BUFFER ; 计算实际地址 MOV R0, A ; R0指向数组元素 MOV A, @R0 ; 读取数组元素 RET
; 遍历数组(求数组元素之和)SUM_ARRAY: MOV R0, #BUFFER ; 数组起始地址 MOV R2, #16 ; 数组长度 CLR A ; 累加器清零 CLR B ; 进位清零SUM_LOOP: ADD A, @R0 ; 累加数组元素 JNC NO_CARRY INC B ; 处理进位NO_CARRY: INC R0 ; 下一个元素 DJNZ R2, SUM_LOOP
; 结果:A=低8位,B=高8位(进位) RET3. 多维数组访问
; 二维数组(3x4矩阵)MATRIX_ROWS EQU 3MATRIX_COLS EQU 4MATRIX_SIZE EQU MATRIX_ROWS * MATRIX_COLS
MATRIX: DS MATRIX_SIZE ; 3x4矩阵
; 访问MATRIX[row][col]; 参数:R6 = 行号(0-2), R7 = 列号(0-3); 返回:A = MATRIX[row][col]ACCESS_MATRIX: MOV A, R6 ; 行号 MOV B, #MATRIX_COLS ; 每行4列 MUL AB ; A = 行号 * 4 ADD A, R7 ; + 列号 ADD A, #MATRIX ; + 矩阵基址 MOV R0, A ; R0指向矩阵元素 MOV A, @R0 ; 读取元素 RET结构体类型的数据组织
1. 定义数据结构
; 定义学生记录结构STUDENT_SIZE EQU 4STUDENT_AGE EQU 0 ; 偏移0:年龄STUDENT_GRADE EQU 1 ; 偏移1:成绩STUDENT_ID_H EQU 2 ; 偏移2:ID高字节STUDENT_ID_L EQU 3 ; 偏移3:ID低字节
; 学生数组(3个学生)STUDENTS: DS STUDENT_SIZE * 3
; 常量学生数据(ROM中的模板)STUDENT_TEMPLATE: DB 18, 85, 0, 1 ; 学生1:18岁,成绩85,ID=0001 DB 19, 90, 0, 2 ; 学生2:19岁,成绩90,ID=0002 DB 20, 78, 0, 3 ; 学生3:20岁,成绩78,ID=00032. 访问结构体数组
; 获取第n个学生的成绩; 参数:R7 = 学生索引(0-2); 返回:A = 成绩GET_STUDENT_GRADE: MOV A, R7 ; 学生索引 MOV B, #STUDENT_SIZE ; 每个学生大小 MUL AB ; A = 索引 * 4 ADD A, #STUDENTS ; + 基址 ADD A, #STUDENT_GRADE ; + 成绩偏移 MOV R0, A ; R0指向成绩字段 MOV A, @R0 ; 读取成绩 RET
; 初始化学生数组INIT_STUDENTS: MOV DPTR, #STUDENT_TEMPLATE MOV R0, #STUDENTS ; RAM目标地址 MOV R2, #3 ; 3个学生INIT_STU_LOOP1: MOV R3, #STUDENT_SIZE ; 每个学生4字节INIT_STU_LOOP2: CLR A MOVC A, @A+DPTR ; 从ROM读取 MOV @R0, A ; 写入RAM INC DPTR INC R0 DJNZ R3, INIT_STU_LOOP2 DJNZ R2, INIT_STU_LOOP1 RET高级技巧:使用宏和标号
1. 定义带类型的数组访问宏
; 定义数组访问宏ARRAY_GET MACRO ARRAY_NAME, INDEX, DEST MOV A, INDEX ADD A, #ARRAY_NAME MOV R0, A MOV DEST, @R0 ENDM
ARRAY_SET MACRO ARRAY_NAME, INDEX, SRC MOV A, INDEX ADD A, #ARRAY_NAME MOV R0, A MOV @R0, SRC ENDM
; 使用宏 MOV R1, #2 ; 索引2 ARRAY_GET BUFFER, R1, A ; A = BUFFER[2]
MOV R1, #3 MOV R2, #0FFH ARRAY_SET BUFFER, R1, R2 ; BUFFER[3] = 0FFH2. 使用标号计算数组大小
; 自动计算数组大小CONST_ARRAY_START: DB 1, 2, 3, 4, 5, 6, 7, 8, 9, 10CONST_ARRAY_END:
CONST_ARRAY_SIZE EQU CONST_ARRAY_END - CONST_ARRAY_START
; 编译时会计算:CONST_ARRAY_SIZE = 10完整示例程序
; 定义常数ORG 1000HPI: DB 22, 7 ; π ≈ 22/7DAYS_IN_MONTH: DB 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
; 定义RAM变量ORG 30HTEMPERATURES: DS 24 ; 24小时温度数据DAILY_MAX: DS 1 ; 日最高温度DAILY_MIN: DS 1 ; 日最低温度
; 主程序ORG 0000H MOV SP, #60H
; 初始化温度数组为20°C CALL INIT_TEMP_ARRAY
; 读取下午2点的温度(索引14) MOV R7, #14 CALL GET_TEMPERATURE ; A = TEMPERATURES[14]
; 查找最高温度 CALL FIND_MAX_TEMP ; A = 最高温度 MOV DAILY_MAX, A
; 使用常数表:获取7月的天数 MOV DPTR, #DAYS_IN_MONTH MOV A, #6 ; 7月是第7个月,索引6 MOVC A, @A+DPTR ; A = 31
SJMP $
; 初始化温度数组INIT_TEMP_ARRAY: MOV R0, #TEMPERATURES MOV R2, #24 MOV R3, #20 ; 初始温度20°CINIT_TEMP_LOOP: MOV @R0, R3 INC R0 DJNZ R2, INIT_TEMP_LOOP RET
; 获取温度值GET_TEMPERATURE: ; R7 = 小时(0-23) MOV A, R7 ADD A, #TEMPERATURES MOV R0, A MOV A, @R0 RET
; 查找最高温度FIND_MAX_TEMP: MOV R0, #TEMPERATURES MOV R2, #24 CLR A ; A = 0(当前最大值)FIND_MAX_LOOP: MOV B, @R0 CJNE A, B, COMPARECOMPARE: JNC NOT_HIGHER ; 如果A >= B,跳过 MOV A, B ; 更新最大值NOT_HIGHER: INC R0 DJNZ R2, FIND_MAX_LOOP RET重要提示:
- ROM常数:使用
DB/DW定义,用MOVC指令访问 - RAM数组:使用
DS预留空间,运行时初始化 - 地址计算:访问数组元素时,基址+偏移量计算地址
- 索引边界:始终检查数组索引是否越界
- 性能考虑:频繁访问的数组放在直接寻址区域(00H-7FH)