计组笔记 08 汇编语言
汇编语言通过指令与伪指令实现对硬件的直接控制,核心在于数据定义、寄存器操作与过程调用机制,并依赖栈完成参数传递与现场保护。 其程序设计遵循结构化思想,通过顺序、分支与循环控制流程,并结合模块化与过程化方法实现复杂功能与代码复用。
计组笔记 08 汇编语言
第8章 汇编语言
适配 8086/MASM 语法
0. 汇编语句的一般形式与约定
- 通式:
[label:] mnemonic operand1[, operand2] ;注释 - 操作数:寄存器 / 立即数 / 存储器(可带符号名、位移、[寄存器])/ 表达式。
- 大小写与空格:不敏感;分号
;之后是注释。 - 一条语句一个功能;空行、仅注释行编译器不处理。
- 常见段框架:
.MODEL SMALL ; 或 TINY/SMALL/MEDIUM/COMPACT/LARGE
.STACK ; 可省长度,默认 1KB(教材默认 1024)
.DATA ; 数据段
var DW 1234h
.CODE
start: ; 程序入口(COM 常用 label,EXE 常配 STARTUP)
mov ax, @data ; 经典 SMALL 初始化
mov ds, ax
; …… Your code ……
EXIT ; 等价于 .EXIT / INT 21h,4Ch
END start
- 内存模型:
- TINY:单段(.COM);SMALL:1 Code + 1 Data;MEDIUM:多 Code,1 Data;COMPACT:1 Code,多 Data;LARGE:多 Code,多 Data(每段≤64KB)。
1. 数据定义与伪指令(Directive)
1.1 数据定义(存储器保留 + 初始化)
| 伪指令 | 大小 | 典型写法 | 说明 | | — | — | — | — | | DB | 1 字节 | DB 12, 0FFh, 'A',"Hi" | 可混合字节常数与字符串 | | DW | 2 字节 | DW 1234h, 0 | 按小端序存放 | | DD | 4 字节 | DD 0ABCDEF0h | 双字 | | DQ | 8 字节 | DQ 12345678h, 9ABCDEF0h | 四字 | | DT | 10 字节 | DT 10 dup(0) | 有的教材用于 BCD/扩展精度 |
- 重复:
DUP(n),如DB 10 DUP(0);嵌套可DB 3 DUP('ABC')。 - 字符串:
"ABC"等价三个字节41h,42h,43h。 - 地址表达式:允许
OFFSET 符号或由编译器计算的表达式(本教材更多用 LEA 装入 EA)。
1.2 命名与类型
EQU:给表达式/常量取名:TABW EQU 2。编译期替换,不占存储。LABEL 类型:给当前位置贴类型化标签(并指明它的段:偏移类型),如:Here LABEL WORD。
1.3 段与程序组织
- 低级段法:
段名 SEGMENT [对齐/组合/类别]
……(段体)
段名 ENDS
1
- 组合关键字(PUBLIC、STACK、MEMORY 等)按教材用于链接器段合并;类别用于说明用途('CODE'、'DATA')。 + **高级段法**(MASM 简化):`.MODEL`、`.STACK [n]`、`.DATA`、`.CODE`。 + `ASSUME`:声明段寄存器与逻辑段关联(简化模式多数由编译器自动处理)。 + `ORG`:设定**当前位置**(常见于设备/引导扇区编程)。 + `END [入口标号]`:**唯一终止语句**;指定可执行入口(EXE)。
1.4 模块化汇编伪指令
PUBLIC 符号:本模块导出符号(变量/过程/标签等)。EXTRN 名:TYPE[, 名:TYPE]:声明外部符号,TYPE 可为BYTE/WORD/DWORD/FAR/NEAR/ABS等。
例:EXTRN puts:FAR, gCount:WORD
1.5 其他“文档类”伪指令
NAME 模块名:目标模块名。TITLE text:页眉标题(打印/列表标题)。SUBTTL text:小标题;PAGE [行数[,列宽]]:分页设置。.STARTUP:设入口准备;.EXIT:返回 DOS(等价INT 21h,4Ch)。
2. 过程(子程序)与调用
2.1 定义与调用
; 定义
ProcName PROC NEAR|FAR
; …… 过程体 ……
RET ; 或 RET n(栈平衡返回)
ProcName ENDP
; 调用
CALL ProcName ; 近调用改 IP;FAR 同时改 CS:IP
- NEAR/FAR:是否跨段;同一代码段内取 NEAR;跨段或 DOS 子程序常取 FAR。
- 返回:
RET [n];RET n会在返回前 弹栈并额外丢弃 n 字节(常用于“被调用者清栈”的参数约定)。
2.2 入口/出口约定与现场保护
- 入口参数:调用时的先决条件(需要哪些寄存器/内存参数)。
- 出口结果:返回后在哪些寄存器或内存可取到结果。
- 现场保护(保存/恢复寄存器)三法(教材原话要点):
- 调用者保存:先
PUSH自己要用的寄存器,返回后POP。 - 被调者保存(最常见):过程开始
PUSH所用寄存器,结束前POP。 - 统一工作寄存器区:用专用内存区保存/恢复(少见,但试题爱考“还有这种方式”)。
- 调用者保存:先
实操惯例:过程体第一行 push ax bx cx dx si di bp(按需),结束前对称 pop …,中间可用 BP 做栈基址访问参数。
2.3 参数传递方式
- 寄存器传参:快、简单,数量受限。
- 存储单元传参:把地址/变量作为“形参”放在约定位置(DS:…);可共享全局。
- 栈传参:
PUSH实参,过程内用BP定框访问,如[BP+4]、[BP+6]……;可配RET n清栈。- 延伸:返回值也可放栈或寄存器(AX/AX:DX)。
2.4 递归与可重入
- 递归:过程调用自身(直接/间接)。考点是“必须使用栈保存返回地址与局部数据”。
- 可重入:过程允许在执行中再次被调用(含中断打断),要求不使用静态易变的全局区,或正确保护它。
3. 指令系统要点
3.1 数据传送/栈/I-O
MOV:不许内存↔内存;不可写MOV CS, …。PUSH/POP:以字为单位更改SP;SS:SP指向栈顶。XCHG:寄存器/存储器互换(不能与立即数)。IN/OUT:立即端口 8 位;16 位端口放 DX。IN AL/AX, DX/OUT DX, AL/AX。XLAT:AL ← [BX + AL](查表)。
3.2 算术/逻辑/移位/比较
ADD/ADC,SUB/SBB,INC/DEC(不改 CF),NEG(若操作数≠0 → CF=1)。CMP:只改旗标;配Jcc。MUL/IMUL、DIV/IDIV:结果位宽翻倍;除法商/余位置记忆(8位:AL/AH;16位:AX/DX)。- 逻辑:
AND/OR/XOR/TEST(TEST不写回)。 - 移位:
SHL/SHR/SAL/SAR;循环:ROL/ROR/RCL/RCR。被移出位→CF;1 位左移OF = 旧MSB ⊕ 新MSB。
3.3 条件与循环控制
- 条件跳转表:
- 判断位:
JZ/JE(ZF),JNZ/JNE,JS/JNS(SF),JO/JNO(OF),JP/JPE/JNP/JPO(PF),JC/JNC(CF)。 - 无符号:
JB/JNAE(CF=1),JAE/JNB(CF=0),JA/JNBE(CF=0∧ZF=0),JBE/JNA(CF=1∨ZF=1)。 - 有符号:
JL/JNGE(SF≠OF),JGE/JNL(SF=OF),JG/JNLE(ZF=0∧SF=OF),JLE/JNG(ZF=1∨SF≠OF)。
- 判断位:
- 计数循环:
LOOP(CX--且CX≠0跳);LOOPE/LOOPZ(再加ZF=1);LOOPNE/LOOPNZ(再加ZF=0)。 - 无条件跳转:
JMP近/远、直接/间接(表驱动)。
3.4 串操作与前缀
MOVS/CMPS/SCAS/STOS/LODS+B/W;隐含DS:SI(源)、ES:DI(目的);
DF=0递增,DF=1递减;REP/REPE/REPNE结合 CX 计数。
4. 结构化程序设计
4.1 顺序结构
- 语句线性执行。注意:更新段寄存器/栈寄存器要成对,并保证数据段有效。
4.2 分支结构
- 二分支:
IF-THEN-ELSE→CMP+ 合适的Jcc+JMP跳过; - 多分支:
- 多次
CMP+ 多个Jcc; - 或“跳转表”——
JMP WORD PTR [BX+SI]等间接转移(段内/间接)。
- 多次
4.3 循环结构
- 计数循环(for):初始化计数 → 体 → 计数/条件 → 回到体首;
CX常用。 - 条件循环(while/do-while):先判后跳或先做后判。
- 嵌套循环:外层与内层的计数寄存器/标志位不要混用;方向标志 DF 的设置在进入串循环前明确
CLD/STD。
5. 过程化编程要点
5.1 过程设计流程
- 明确问题定义
- 建立数学模型
- 确定算法/处理方案
- 画流程图
- 编写程序(结构化,过程化)
- 上机调试
- 试运行与分析结果
- 整理/投人运行
5.2 过程接口(I/O)与注释
- 入口:需要参数、起始状态、被改动资源;出口:返回值与状态。
- 注释建议写明:用途、输入、输出、破坏寄存器、被调用过程等(试卷会考“应当说明哪些内容”)。
5.3 参数传递细化
- 寄存器(直接、显式、常用)
- 立即数(把常量写在指令中)
- 存储单元(通过变量表地址传入/传出)
- 栈(最灵活;可嵌套、可递归;配
BP定位参数)
过程返回多结果:寄存器 + 存储单元混合最常见;或在调用点分配输出缓冲区地址传入。
5.4 递归/嵌套调用
- 递归:每次调用都生成新的返回地址与局部副本;必须正确
PUSH/POP,可配帧指针 BP 管理局部变量。 - 嵌套:一个过程内部
CALL另一个;需注意调用深度与寄存器保护。
6. 易错
MOV不能 mem↔mem;XCHG也不行(寄存器必须参与)。PUSH/POP对象为字;8086 栈向低地址生长(SP-=2入栈)。INC/DEC不影响 CF;NEG若操作数非 0 → CF=1。IN/OUT:立即端口只有 8 位;16 位端口号放 DX。CMP/TEST只改旗标、不写回。- LEA 与
MOV区分:LEA reg, mem取有效地址(不访存);MOV reg, mem取内容(访存)。 CBW/CWD是符号扩展(AL→AX、AX→DX:AX)。DIV/IDIV若除数为 0 或商溢出 → 异常(题目常问结果寄存器位置)。- 条件转移:无符号用
CF/ZF,有符号用SF与OF的关系。 - 串指令:方向由 DF 控制;进入循环前记得
CLD(正向)或STD(反向);计数在 CX。 - 过程:
NEAR只改IP;FAR同时改CS:IP;RET n会清理n字节参数。 - 递归/可重入:必须依赖栈;避免使用共享可变全局(或妥善保护)。
.STARTUP/.EXIT是伪指令层面的入口/退出封装;END 入口指出程序起点。PUBLIC/EXTRN:模块间符号导出/声明,EXTRN 名:类型的类型要写对(FAR/NEAR/BYTE/WORD等)。
7. 典型模板
7.1 SMALL 模型 + 过程 + 栈传参
.MODEL SMALL
.STACK 100h
.DATA
msg DB "sum=",0
a DW 3
b DW 5
.CODE
start:
mov ax, @data
mov ds, ax
; 栈传参:右到左压栈
push b
push a
call Sum2 ; AX ← a+b
add sp, 4 ; 调用者清栈(也可在被调者用 RET 4)
; …… 使用 AX 的结果 ……
EXIT
;-------------------------
; int Sum2(word x, word y) -> AX
Sum2 PROC NEAR
push bp
mov bp, sp
push bx ; 现场保护(示例)
mov ax, [bp+4] ; y
mov bx, [bp+6] ; x
add ax, bx
pop bx
pop bp
ret ; 若被调者清栈可写:ret 4
Sum2 ENDP
;-------------------------
END start
7.2 串搬运 + 条件/计数循环
cld ; DF=0,正向
mov cx, count
mov si, OFFSET src
mov di, OFFSET dst
rep movsb ; 拷贝 CX 个字节
; 比较直到找到 0
mov cx, maxlen
mov di, OFFSET buf
mov al, 0
repne scasb ; 找 0:当 AL≠[ES:DI] 时继续,ZF=1 表示命中
jnz not_found
; found...
8. 程序设计与文档伪指令
TITLE/SUBTTL:打印/列表标题;PAGE rows[,cols]:分页设置;NAME:模块名;- 过程化文档:过程接口(入口/出口/破坏寄存器)、参数说明与返回值、寄存器保护策略、调用关系图
本文由作者按照 CC BY-NC 4.0. 进行授权
...

Comments
评论区