8086 汇编语言从入门到实战:寻址方式 + 经典作业案例深度复盘
一、前言
很多计算机专业的同学初次接触汇编语言时,都会被寄存器、段寻址、各种间接 / 基址变址寻址搞得一头雾水。我们习惯了 Python、C 语言这种高度封装的高级语言,不用关心数据存在内存的哪个位置、CPU 如何逐条执行指令,而汇编语言相当于一把 “透视镜”,让我们直接触摸计算机底层的运行逻辑。
本文结合本学期汇编课程的三道经典实验练习题,从寄存器基础、内存寻址方式、数组批量处理、数据统计计算四个维度,复盘汇编核心知识点,同时附上可直接运行的完整代码、踩坑经验总结,不管是期末复习、作业参考还是入门学习都可以直接使用。
二、汇编前置核心知识点梳理
1. 8086 寄存器基础
16 位 8086CPU 常用寄存器分为两大类:
通用寄存器(16 位):AX、BX、CX、DX、SI、DI、BP、SP,其中AX、BX、CX、DX可以拆分为两个 8 位寄存器(如AX=AH高8位+AL低8位),用来处理单字节数据。
段寄存器(16 位):CS(代码段)、DS(数据段)、ES(附加段)、SS(栈段),用来存放段基地址,程序必须先给DS赋值才能访问自定义数据段里的变量。
三种高频寻址方式
| 寻址方式 | 写法示例 | 核心作用 |
|---|---|---|
| 寄存器间接寻址 | [SI]、[DI] | 用单个寄存器充当内存偏移,适合一维数组顺序遍历 |
| 基址变址寻址 | [BX+SI]、[BX+DI] | BX做数据块基准起始地址,变址寄存器遍历内部元素,适合二维表格、多组数据处理 |
| 相对基址变址寻址 | [BX+SI+10H] | 在基址变址基础上增加固定偏移,直接访问多块连续内存区域 |
常用伪指令
DB:定义字节(8 位,1 字节),适合存放字符、单个 0~255 数值
DW:定义字(16 位,2 字节),适合存放成绩、工资这类整数
DD:定义双字(32 位,4 字节),适合超大数值(总收入、大数除法场景)
DUP(n,数据):批量开辟连续内存,比如DB 20 DUP(?)一次性申请 20 字节空白内存
三、三大经典实战案例详解(附完整可运行代码)
案例 1:内存数据批量复制(寻址方式基础演练)
1. 题目需求
预先开辟30H字节空白内存,从偏移30H开始存放 0~15 共 16 个字节数据,将这组数据分别复制到内存偏移00H、10H、20H三块区域,练习寄存器间接、基址变址寻址。
assume cs:codesg, ds:data
data segment db 30H dup (?)
db 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
data ends
codesg segment
start:
mov ax, data
mov ds, ax
mov si, 30H ;源数据起始偏移
mov di, 0 ;第一块目标区域偏移
mov bx, 10H ;第二块数据基准偏移
mov cx, 10H ;循环16次
next: mov al, [si] ;寄存器间接寻址:读取源数据
mov [di], al ;复制到00H~0FH区域
mov [bx+di], al ;基址变址寻址:复制到10H~1FH区域
mov [bx+di+10H], al ;相对基址变址寻址:复制到20H~2FH区域
inc di
inc si
loop next
mov ax,4c00h
int 21h
codesg ends
end start
案例 2:二维数组求和(工资统计)
1. 题目需求
8 名工程师,第一行 DW 存储基本工资、第二行 DW 存储绩效工资,第三行预留空白 DW,计算每位员工总工资存入对应位置
寄存器间接寻址
assume cs:codesg, ds:datasg
datasg segment
dw 6290, 7230, 2943, 3360, 7469, 6871, 3067, 3086
dw 7288, 7160, 5733, 7030, 5281, 6891, 4853, 4539
dw 0,0,0,0,0,0,0,0
datasg ends
codesg segment
start:
mov ax, datasg
mov ds, ax
mov cx, 8
mov si, 0
L1:
mov ax, [si]
add ax, [si+16]
mov [si+32], ax
add si, 2
loop L1
mov ax,4c00h
int 21h
codesg ends
end start
案例 3:二维成绩表总分统计(双层循环 + 栈段使用)
1. 题目需求
5 名学生,每人 4 门课程成绩,每条记录第 5 个 DW 用来存储总分,使用双层循环累加每一位同学总成绩,同时手动初始化栈段,练习栈寄存器SS、SP的使用。
assume cs:codesg, ds:datasg, ss:stacksg
datasg segment
dw 54, 74, 71, 52, 0
dw 68, 54, 93, 95, 0
dw 81, 52, 97, 67, 0
dw 98, 77, 69, 99, 0
dw 79, 71, 69, 73, 0
datasg ends
stacksg segment
dw 8 dup(0)
stacksg ends
codesg segment
start:
;栈段初始化
mov ax, stacksg
mov ss, ax
mov sp, 16 ;数据段挂载
mov ax, datasg
mov ds, ax
mov cx, 5
mov bx, 0
outer:
push cx ;外层循环CX入栈保护,避免被内层循环覆盖
mov ax, 0
mov si, 0
mov cx, 4
inner:
add ax, [bx+si]
add si, 2
loop inner
mov [bx+8], ax ;总成绩存入每条记录末尾
pop cx
add bx, 10 ;单条学生记录:5个DW=10字节
loop outer
mov ax,4c00h
int 21h
codesg ends
end start
