内存单元

描述一个内存单元需要两种信息:

  1. 内存单元的地址
  2. 内存单元的长度(类型:字、字节)

[bx] 可以标识一个内存单元,偏移地址在 bx 寄存器中,段地址在 ds 寄存器中。

约定符号

(ax) 表示取 ax 寄存器中的内容。

idata 表示常量。

[bx]

1
mov ax, [bx]

bx 寄存器中存放的数据作为偏移地址 EA,ds 寄存器中的数据作为段地址 SA,将 SA:EA 中的数据送入 ax 中,即 (ax) = ((ds)*16 + (bx))

1
mov [bx], ax

bx 寄存器中存放的数据作为偏移地址 EA,ds 寄存器中的数据作为段地址 SA,将 ax 寄存器中的数据送入内存 SA:EA 处,即 ((ds)*16 + (bx)) = (ax)

loop 指令

loop 指令格式:

1
loop 标号

CPU 执行 loop 指令时的操作:

  1. (cx) = (cx) - 1
  2. 判断 cx 寄存器中的值,不为零就转到标号执行,为零向下执行

计算 2122^12

1
2
3
4
5
6
7
8
9
10
assume cs:code
code segment
mov ax, 2
mov cx, 11
s: add ax, ax
loop s
mov ax, 4c00h
int 21h
code ends
end
  1. 在 cx 中存放循环次数
  2. loop 指令中的标号要写在前面
  3. 要循环执行的代码写在标号和 loop 指令之间

代码框架:

1
2
3
4
    mov cx, 循环次数
s: 循环执行的程序段
循环执行的程序段
loop s

debug 与 masm 对指令的不同处理

masm 会将 mov ax, [0] 理解为 mov ax, 0 将常量 0 送入 ax。
debug 会将 mov ax, [0] 理解为将内存 ds:0 处的值送入 ax。

为了可以在汇编源码中达到相同的目的,需要在 [0] 之前显示地加上段寄存器的名称。

将内存单元中的数据送入 al:

1
mov al, ds:[0]

loop 和 [bx] 的联合应用

适合处理地址连续的内存单元中的数据。

计算 ffff:0 ~ ffff:b 单元中的数据的和,结果存储在 dx 中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
assume cs:code
code segment
mov ax, 0ffffh
mov ds, ax
mov bx, 0
mov cx, 12
s:mov ah, 0
mov al, [bx]
add dx, ax
inc bx
loop s
mov ax, 4c00h
int 21h
code ends
end

段前缀

可以在访问内存单元的指令中显示地指定段地址所在的寄存器。

例如:

1
2
3
4
5
6
7
mov ax, ds:[bx]
mov ax, cs:[bx]
mov ax, ss:[bx]
mov ax, es:[bx]
mov ax, ds:[bx]
mov ax, ss:[0]
mov ax, cs:[0]

其中 ds: cs: ss: es: 称为段前缀

将 ffff:0 ~ ffff:b 单元中的数据复制到 0:200 ~ 0:20b 单元中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
assume cs:code
code segment
mov ax, 0ffffh
mov ds, ax
mov ax, 20h
mov es, ax
mov cx, 12
mov bx, 0
s:mov al, [bx]
mov es:[bx], al
inc bx
loop s
mov ax, 4c20h
int 21h
code ends
end

向内存 0:200 ~ 0:23F 依次传送数据 0 ~ 63(3FH)。

1
2
3
4
5
6
7
8
9
10
11
12
13
assume cs:code
code segment
mov ax, 20h
mov ds, ax
mov bx, 0
mov cx, 64
s:mov [bx], bl
inc bx
loop s
mov ax, 4c00h
int 21h
code ends
end