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 = 0
INIT_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_LOOP
END_OF_STRING:
RET

2. 访问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位(进位)
RET

3. 多维数组访问#

; 二维数组(3x4矩阵)
MATRIX_ROWS EQU 3
MATRIX_COLS EQU 4
MATRIX_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 4
STUDENT_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=0003

2. 访问结构体数组#

; 获取第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] = 0FFH

2. 使用标号计算数组大小#

; 自动计算数组大小
CONST_ARRAY_START:
DB 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
CONST_ARRAY_END:
CONST_ARRAY_SIZE EQU CONST_ARRAY_END - CONST_ARRAY_START
; 编译时会计算:CONST_ARRAY_SIZE = 10

完整示例程序#

; 定义常数
ORG 1000H
PI: DB 22, 7 ; π ≈ 22/7
DAYS_IN_MONTH:
DB 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
; 定义RAM变量
ORG 30H
TEMPERATURES: 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°C
INIT_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, COMPARE
COMPARE:
JNC NOT_HIGHER ; 如果A >= B,跳过
MOV A, B ; 更新最大值
NOT_HIGHER:
INC R0
DJNZ R2, FIND_MAX_LOOP
RET

重要提示:#

  1. ROM常数:使用DB/DW定义,用MOVC指令访问
  2. RAM数组:使用DS预留空间,运行时初始化
  3. 地址计算:访问数组元素时,基址+偏移量计算地址
  4. 索引边界:始终检查数组索引是否越界
  5. 性能考虑:频繁访问的数组放在直接寻址区域(00H-7FH)
汇编代码初始化数组
https://www.mintlab.top/posts/stc8g汇编笔记/asm_array/
作者
Mint
发布于
2025-12-30
许可协议
CC BY-NC-SA 4.0