目录:https://blog.csdn.net/qq_43098197/article/details/124532401
[BX]
[bx]
:和 [x]
一样表示偏移地址,不过该偏移地址不是常量,而是存储在 bx
寄存器中。
mov ax, 2000h
mov ds, ax
mov bx, 1000h
mov ax, [bx] ;ds:bx 2000:1000
Loop
loop
:循环。
格式:
汇编指令
mov cx, X ; 设置循环次数为 X
标号: ; 循环开始
汇编指令 ; 循环中的指令
汇编指令
loop 标号 ; 循环结束,若 CX 计数器不为 0,则继续循环
在 Debug 中跟踪 loop
一条汇编指令需要一次 T
,当汇编指令或 loop 循环次数多了,T 起来挺麻烦的,可以使用下面的指令:
-g CS:IP
:直接执行到指定位置。
-p
:当执行 Loop 标号
指令时,该指令用 p
指令可以直接完成循环。
Debug 和 汇编汇编器 masm 对指令的不同处理
Debug 写入
masm 编译后 debug
assume cs:code
code segment
mov ax, 2000h
mov ds, ax
mov al, [0]
mov bl, [1]
mov cl, [2]
mov dl, [3]
mov ax, 4c00H
int 21h
code ends
end
第一种方式:将 [x]
识别为一个内存单元
第二种方式:将 [x]
识别为一个常量 x
解决方案: 将偏移地址送入 bx 寄存器中,使用 [bx]
的方式来访问内存单元。
assume cs:code
code segment
mov ax, 2000h
mov ds, ax
mov bx, 0
mov al, [bx]
mov bl, ds:[1]
mov cl, ds:[2]
mov dl, ds:[3]
mov ax, 4c00H
int 21h
code ends
end
解决方案: 源程序中将 [x]
写成 段寄存器:[x]
的形式
assume cs:code
code segment
mov ax, 2000h
mov ds, ax
mov al, ds:[0]
mov bl, ds:[1]
mov cl, ds:[2]
mov dl, ds:[3]
mov ax, 4c00H
int 21h
code ends
end
使用 Loop 需要注意的问题
题目: 计算 ffff:0 ~ ffff:b 单元中的数据的和,结果存储在 dx 中。
分析:
-
运算后的结果是否会超出 dx 所能存储的范围?
ffff:0~ffff:b
内存单元中的数据是字节型数据,范围在 0~255 之间,12 个这样的数据相加,结果不会大于 65535,可以在 dx 中存放。 -
我们能否将
ffff:0~ffff:b
中的数据直接累加到dx
中?不能,因为该范围中的数据是 8 位的,不能直接赋值给 16 位寄存器。
-
我们能否将
ffff:0~ffff:b
中的数据累加到dl
中?不能,因为可能造成进位丢失。
解决: 如何将 ffff:0~ffff:b
中的 8 位数据,累加到 16 位寄存器 dx 中?
- 使用一个 16 位寄存器作为中介。
- 将内存单元中的 8 位数据赋值给一个 16 位寄存器 ah 或 al 中。
- 再将 ax 赋值给 dx。
程序:
assume cs:code
code segment
mov ax, 0ffffh
mov ds, ax
mov bx, 0 ; ds:bx
mov dx, 0 ; 累加器
mov ax, 0
mov cx, 12 ; 循环计数器
s:mov al, ds:[bx]
mov ah, 0
add dx, ax
inc bx ; 操作数+1 也就是指向下一个字节
loop s
mov ax, 4c00h
int 21h
code ends
end
段前缀
mov ax, ds:[bx]
mov ax, cs:[bx]
mov ax, ss:[bx]
mov ax, cs:[0]
mov ax, ss:[0]
在访问内存单元的指令中,用于显示的指明内存单元的段地址的 ds:
、cs:
、ss:
、es:
,称为段前缀。
一段安全的空间
内存中某些地方可能存放着重要的系统数据或代码,若我们改写了它们,或许会导致系统出问题。
因此在向某段内存单元写入数据时,要先论证该段地址没有存放重要数据与代码。
一段相对安全的段: 0000:0200~0000:02ff