汇编中[...]与(...)的规定,loop指令及其应用
[......] 在汇编语法的规则 中,这表示一个内存单元
| 指令 | 段地址 | 偏移地址 | 操作单位 |
| mov ax,[0] | 在DS中 | 在[0]中 | 字 |
| mov al,[0] | 在DS中 | 在[0]中 | 字节 |
| mov ax,[bx] | 在DS中 | 在[bx]中 | 字 |
| mov al,[bx] | 在DS中 | 在[bx]中 | 字节 |
(......) 这是为学习方便做出的约定 ,表示一个内存单元或寄存中的内容
| 描述对象 | 描述方法 | 描述对象 | 描述方法 |
| ax中的内容为0010H | (ax)=0010H | 2000:1000处的内容为0010H | (21000H)=0010H |
| mov ax,[2]的功能 | (ax)=((ds)*16+2) | mov [2],ax的功能 | ((ds)*16+2)=(ax) |
| add ax,2的功能 | (ax)=(ax)+2 | add ax,bx的功能 | (ax)=(ax)+(bx) |
| push ax的功能 |
(sp)=(sp)-2 ((ss)*16+(sp))=(ax) | pop ax的功能 |
(ax)=((ss)*16+(sp)) (sp)=(sp)+2 |
Loop指令
1、功能:实现循环(计数型循环)
2、指令格式:loop + 标号
; 功能:计算 1+2+...+10,结果存AX寄存器
MOV CX, 10 ; 1. 初始化循环次数=10(CX=10,循环10次)
MOV AX, 0 ; 2. 结果寄存器AX清零(用于存累加和)
SUM_LOOP: ; 3. 循环标签(loop跳转目标)
ADD AX, CX ; 4. 循环体:AX = AX + CX(第一次加10,第二次加9...)
LOOP SUM_LOOP ; 5. loop核心:CX -= 1;若CX≠0,跳回SUM_LOOP;CX=0则退出
; 执行后:AX=55(1+2+...+10的结果)
3、cpu执行loop指令的时候要进行的操作,如下
3.1 (cx)=(cx)-1;
3.2 判断cx中的值
不为0,则转至标号处执行程序
如果为0,则跳出循环,向下执行;
下面看一个具体的实例

CX:计数寄存器
loop每循环一次,CX的值就会减1
在debug中,mov al,[0]的功能是:
将DS:0存储单元的值传给AL
访问连续的内存单元---loop和[BX]联手
问题:计算ffff:0~ffff:b字节单元中的数据的和,结果存储在dx中

代码解读:
assume cs:code ; 伪指令:假设代码段寄存器cs指向code段(仅编译提示,无执行逻辑)
code segment ; 定义代码段开始
mov ax,0ffffH ; 将立即数0FFFFH送入ax(8086不能直接给段寄存器赋值,需通过通用寄存器中转)
mov ds,ax ; 将ax的值(0FFFFH)送入数据段寄存器ds,此时ds=0FFFFH(数据段基址)
mov bx,0 ; bx=0(作为内存偏移地址,初始指向ds:0,即0FFFF:0000H)
mov dx,0 ; dx=0(累加器初始化,用于存储12个字节的累加和)
mov cx,12 ; cx=12(loop循环计数器,控制循环执行12次)
; 循环体开始(标签s)
s:mov al,[bx] ; 读取ds:bx(0FFFF:bx)地址处的1个字节,送入al(8位寄存器)
mov ah,0 ; ah=0(将al的8位数值扩展为ax的16位数值,避免累加时高位干扰)
add dx,ax ; 将ax(扩展后的字节值)加到dx中(dx = dx + ax)
inc bx ; bx自增1(偏移地址+1,指向下一个字节)
loop s ; cx自减1,若cx≠0则跳回标签s继续循环;直到cx=0退出循环
mov ax,4c00h ; ax=4C00H(DOS中断功能号:程序正常退出)
int 21h ; 调用DOS 21H中断,执行程序退出操作
code ends ; 代码段结束
end ; 汇编程序结束(指定程序入口,此处默认从代码段起始处执行)
段前缀的使用
问题:将内存ffff:0~ffff:b中的数据拷贝到0:200~0:20b单元中
| ffff:0 | 0020:0 | ||
| ffff:1 | 0020:1 | ||
| ffff:2 | 0020:2 | ||
| ffff:3 | 0020:3 | ||
| ffff:4 | 0020:4 | ||
| ffff:5 | 0020:5 | ||
| ffff:6 | 0020:6 | ||
| ffff:7 | 0020:7 | ||
| ffff:8 | 0020:8 | ||
| ffff:9 | 0020:9 | ||
| ffff:a | 0020:a | ||
| ffff:b | 0020:b |

assume cs:code ; 伪指令:声明cs寄存器关联code段(仅编译提示,无执行逻辑)
code segment ; 定义代码段开始
mov bx,0 ; bx=0(偏移地址初始化,同时作为源/目标地址的偏移量,初始指向0号偏移)
mov cx,12 ; cx=12(loop循环计数器,控制拷贝12个字节)
; 循环体开始(标签s)
s:mov ax,0ffffh ; ax=0FFFFH(给数据段寄存器ds赋值的中转,8086不支持直接给ds赋值)
mov ds,ax ; ds=0FFFFH(将ds指向源数据段:0FFFFH段)
mov dl,[bx] ; 读取源地址 ds:bx(0FFFF:bx)的1个字节,存入dl(8位寄存器,临时存储)
mov ax,0020h ; ax=0020H(中转赋值)
mov ds,ax ; ds=0020H(将ds指向目标数据段:0020H段)
mov [bx],dl ; 将dl中临时存储的字节,写入目标地址 ds:bx(0020:bx)
inc bx ; bx自增1(偏移地址+1,指向下一个字节)
loop s ; cx自减1,若cx≠0则跳回s继续循环;cx=0时退出循环
mov ax,4c00h ; ax=4C00H(DOS中断功能号:程序正常退出)
int 21h ; 调用DOS 21H中断,执行退出操作
code ends ; 代码段结束
end ; 汇编程序结束(入口默认是代码段起始处)
通过分离ds(源段)和es(目标段),避免循环内反复切换数据段,是 8086 汇编中内存拷贝的「优化写法」,如下

代码解读;
assume cs:code
code segment
; 1. 初始化源段寄存器ds、目标段寄存器es(仅执行1次,而非循环内反复执行)
mov ax,0ffffh
mov ds,ax ; ds = 0FFFFH(源数据段:0FFFF0H + bx)
mov ax,0020h
mov es,ax ; es = 0020H(目标附加段:00200H + bx)
; 2. 初始化偏移地址和循环计数器
mov bx,0 ; bx = 0(源/目标地址的偏移量,初始指向0号偏移)
mov cx,12 ; cx = 12(控制循环执行12次)
; 3. 循环拷贝(核心优化:无需切换段寄存器)
s:mov dl,[bx] ; 读取源地址 ds:bx → dl(8位临时存储)
mov es:[bx],dl ; 写入目标地址 es:bx ← dl(直接用es指定目标段)
inc bx ; 偏移地址+1,指向下一个字节
loop s ; cx-1,非0则跳回s
; 4. 程序退出
mov ax,4c00h
int 21h
code ends
end
es(Extra Segment)是 8086 的附加段寄存器,专门用于「数据读写的辅助段寻址」,常见于:
- 内存拷贝 / 数据块移动(分离源段
ds和目标段es); - 字符串操作指令(如
movsb、stosb)的默认目标段; - 避免反复切换
ds导致的效率损耗。
本代码中 mov es:[bx],dl 是「显式段超越前缀」写法 —— 明确指定用es作为段寄存器,而非默认的ds,这是 8086 汇编的标准写法。
DW:define word 定义字型数据
在8086CPU中,字型大小为16位
类似有的还有:
dw 定义一个字
db 定义一个字节
dd 定义一个双字
问题:下面使用dw编程计算8个数据的和,结果存放在ax寄存器中

代码解读
assume cs:code
code segment
; 在CS寄存器中定义8个16位字数据(dw=define word,每个占2字节,共16字节)
dw 0123H, 0456H, 0789H, 0ABCH, 0DEFH, 0FEDH, 0CBAH, 0987H
start: ; 显式指定程序入口(避免CPU执行数据区)
mov bx, 0 ; bx=0(偏移地址,指向第一个字数据)
mov ax, 0 ; ax=0(累加器,初始化累加和)
mov cx, 8 ; cx=8(循环计数器,匹配8个数据,无越界)
; 循环累加:每次取1个16位字,偏移+2
s: add ax, cs:[bx] ; ax = ax + 代码段中bx偏移的16位数据
add bx, 2 ; bx+2(指向下一个16位字)
loop s ; cx-1,非0则跳回s
; DOS中断退出程序
mov ax, 4c00h
int 21h
code ends
end start ; 指定程序入口为start标签(核心修正)
数据存储如下
| 23 | CS:0 | 数据区 |
| 01 | CS:1 | |
| 56 | CS:2 | |
| 04 | CS:3 | |
| 89 | CS:4 | |
| 07 | CS:5 | |
| BC | CS:6 | |
| 0A | CS:7 | |
| EF | CS:8 | |
| 0D | CS:9 | |
| ED | CS:A | |
| 0F | CS:B | |
| BA | CS:C | |
| 0C | CS:D | |
| 87 | CS:E | |
| 09 | CS:F | |
| CS:10 | 代码区 | |
| CS:11 | ||
| CS:12 | ||
| CS:13 | ||
| CS:14 | ||
| CS:15 |

浙公网安备 33010602011771号