Pil0tXia 的书房 Pil0tXia 的书房
首页
  • 第一章 操作系统引论
  • 第二章 进程的描述与控制
  • 第三章 处理机调度与死锁
  • 第四章 存储器管理
  • 第五章 虚拟存储器
  • 期末考试备考
汇编语言课程笔记
GitHub (opens new window)
首页
  • 第一章 操作系统引论
  • 第二章 进程的描述与控制
  • 第三章 处理机调度与死锁
  • 第四章 存储器管理
  • 第五章 虚拟存储器
  • 期末考试备考
汇编语言课程笔记
GitHub (opens new window)
  • 汇编语言课程笔记

    • 课堂速记
  • 《汇编语言》第三版阅读笔记

    • 第一章 基础知识
    • 第二章 寄存器
    • 第三章 寄存器(内存访问)
    • 第四章 第一个程序
    • 第五章 [BX]和loop指令
      • 5.1 [BX]
      • 5.2 Loop指令
      • 5.3 在Debug中跟踪用loop指令实现的循环程序
      • 5.4 Debug和汇编编译器masm对指令的不同处理
      • 5.5 loop和[bx]的联合应用
      • 5.6 段前缀
      • 5.7 一段安全的空间
      • 5.8 段前缀的使用
    • 第六章 包含多个段的程序
    • 第七章 更灵活的定位内存地址的方法
    • 第八章 数据处理的两个基本问题
    • 第九章 转移指令的原理
    • 第十章 CALL和RET指令
    • 第十一章 标志寄存器
    • 第十二章 内中断
  • 汇编语言
  • 《汇编语言》第三版阅读笔记
Pil0tXia
2023-01-05
目录

第五章 [BX]和loop指令

# 第五章 [BX] 和 loop 指令

1. [bx] 和内存单元的描述

[bx] 表示一个内存单元,该内存单元的段地址位于 ds 中,偏移地址位于 bx 中。 该内存单元的完整地址为: ds*16 + bx。

2. loop

循环指令。指令格式为:loop 标号
该指令分两步执行。

第一步,计算 cx = cx -1
第二步,判断 cx 中的值,不为零则跳转至标号出执行程序,如果为零则向下执行。

3. 我们定义的描述性的符号:“()”

“()” 表示一个内存单元或寄存器的内容。也即是存储器中存储的值。

“()” 中的元素可以有 3 中类型:寄存器名、段寄存器名、内存单元的物理地址(一个 20 位数据)。

4. 约定符号 idata 表示常量

在以后的学习中我们约定 idata 表示一个常量。

# 5.1 [BX]

[bx] 表示一个内存单元。

mov ax, [bx] 代码的含义:将 ds:bx 所指向内存单元的内容放入 ax 寄存器中。即:(ax)=((ds*16)+(bx))

mov [bx], ax 代码的含义:将 ax 中的内容放入 ds:bx 所指向的内存单元中。即:((ds*16)+(bx))=(ax)

# 5.2 Loop 指令

首先 loop 指令的格式是:loop 标号。该指令分两步执行:

第一步, 计算 cx = cx - 1;
第二步,判断 cx 中的值,不为零则跳转至标号处执行程序,如果为零则向下执行。

一般使用 loop 指令实现循环功能。格式如下:

    mov cx, n
s:  add ax, ax
    loop s
1
2
3
1
2
3

以上代码会循环执行 n 次。(n >= 0)

# 5.3 在 Debug 中跟踪用 loop 指令实现的循环程序

使用 Debug 调试程序时,有几条经常用到的指令。

T 指令,单步执行指令。

g 指令,跳至断点,从当前 IP 执行至指定 IP 处。"g 0012" 表示程序由当前位置执行至 DS:0012 处。

p 指令,循环执行指令,p 指令用于执行完当前次数。

# 5.4 Debug 和汇编编译器 masm 对指令的不同处理

Debug 和汇编编译器 masm 对形如 “mov ax, [0]” 这类指令的处理是不同的。debug 将 "[0]" 看做是一个内存单元,该内存单元的地址是 ds*6 + 0。而编译器直接将 “[0]” 看做立即数 0。因此有如下约定。

(1)在汇编源程序中,如果指令访问一个内存单元,则在指令中必须用 "[...]" 来表示内存单元,如果在 “[...]” 里用一个常量 idata 直接给出内存单元的偏移地址,就要在 “[]” 的前面显式的给出段地址所在的段寄存器。

(2)如果在 “[]” 里面用寄存器,比如 bx, 间接给出内存单元的偏移地址,则段地址默认在 ds 中。当然,也可以显式的给出段地址所在的段寄存器。

以上两点概括来说就是,如果内存单元的偏移地址使用立即数给出,则必须显式指明其段地址所在的段寄存器。

# 5.5 loop 和 [bx] 的联合应用

通过 loop 和 [bx] 联合应用实现对连续内存单元的操作实例:

    ...
    mov bx, 0
    mov cx, 50

s:  mov ax, [bx]
    inc bx
    loop s
    ...
1
2
3
4
5
6
7
8
1
2
3
4
5
6
7
8

以上代码通过循环实现了对内存单元 DS:0000H~DS:0032H 内容的操作。

# 5.6 段前缀

如果内存单元的偏移地址由 bx 给出,如 “mov ax, [bx]”,则段地址默认位于 ds 中。我们也可以在访问内存单元的指令中显式的给出内存单元段地址所在的段寄存器。比如:

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

这些出现在访问内存单元的指令中,用于显式的指明内存单元的段地址的 “ds:”、“cs:”、“ss:”、“es:”,在汇编语言中称为段前缀。

# 5.7 一段安全的空间

(1)我们需要直接向一段内存汇总写入内容;

(2)这段内存空间不应当存放系统或其他程序的数据或代码,否则写入操作很可能引发错误;

(3)DOS 方式下,一般情况,0:200~0:2ff 空间中没有系统或其他程序的数据或代码;

(4)以后,我们需要直接向一段内存中写入内容时,就使用 0:200~0:2ff 这段空间。

# 5.8 段前缀的使用

当需要操作的内存空间跨段时,显式的使用段前缀给出内存单元的段地址,可以避免在循环中对 ds 的重复设置。

也即是说一个内存单元的段地址不仅仅可以由 ds 给出,也可以通过 cs、ss、es 给出。


上次更新: 2023/01/20, 21:30:41

← 第四章 第一个程序 第六章 包含多个段的程序→

Copyright © 2022-2023 Pil0tXia | CC BY-NC-SA 4.0 Licensed | 苏ICP备2023001491号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式