汇编语言学习笔记(五):[BX] 和 loop 指令

学习参考:汇编语言(第2版)王爽

  • [bx]
  • loop 指令
  • 段前缀
  • 一段安全的空间

[bx]

[bx] 表示一个内存单元,它的偏移地址在 bx 中,比如下面的指令

1
mov ax,[bx]

将一个内存单元的内容送入 ax,这个内存单元的长度为 2 字节(字单元),存放一个字,偏移地址 EA 在 bx 中,段地址 SA 在 ds 中。即 (ax)=((ds)*16+(bx))

1
mov al,[bx]

将一个内存单元的内容送入 al,这个内存单元的长度为 1 字节(字节单元),存放一个字节,偏移地址在 bx 中,段地址在 ds 中

loop 指令

loop 指令的格式是:loop 标号,CPU 执行 loop 指令的时候,要进行两步操作

  1. (cx)=(cx)-1
  2. 判断 cx 中的值,不为零则转至标号处执行程序,如果为零则向下执行

上述中,可见 cx 中的值影响着 loop 指令的执行结果。通常 cx 中存放循环次数

例如,求 2^12 的结果

1
2
3
4
5
6
7
8
9
10
11
12
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

程序中出现了一个标号 s: ,这个实际上标识了一条指令:add ax,ax

根据程序,我们可以总结出用 cx 和 loop 指令相配合实现循环功能的 3 个要点:

  1. 在 cx 中存放循环次数
  2. loop 指令中的标号所标识地址要在前面
  3. 要循环执行的程序段,要写在标号和 loop 指令的中间

用 cx 和 loop 指令相配合实现循环功能的程序框架如下:

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

例程2:用加法计算 123*236,结果存在 ax 中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
assume cs:code

code segment
mov ax,0

mov cx,123
s:
add ax,236
loop s

mov ax,4c00h
int 21h
code ends
end

段前缀

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

  1. mov ax,ds:[bx]
    将一个内存单元的内容送入 ax,这个内存单元的长度为 2 字节(字单元),存放一个字,偏移地址在 bx 中,段地址在 ds 中
  2. mov ax,cs:[bx]
    将一个内存单元的内容送入 ax,这个内存单元的长度为 2 字节(字单元),存放一个字,偏移地址在 bx 中,段地址在 cs 中
  3. mov ax,ss:[bx]
    将一个内存单元的内容送入 ax,这个内存单元的长度为 2 字节(字单元),存放一个字,偏移地址在 bx 中,段地址在 ss 中
  4. mov ax,es:[bx]
    将一个内存单元的内容送入 ax,这个内存单元的长度为 2 字节(字单元),存放一个字,偏移地址在 bx 中,段地址在 es 中

这种显式地指明内存单元的段地址的 “ds:” “cs:” “ss:” “es:”,在汇编中称为段前缀

一段安全的空间

  1. 我们需要直接向一段内存中写入内容;
  2. 这段内存空间不应该存放系统或其他程序的数据或代码,否则写入操作很可能引发错误;
  3. DOS 方式下,一般情况,0:200~0:2ff 空间中没有系统或其他程序的数据或代码;
  4. 以后,我们需要直接向一段内存中写入内容时,就使用 0:200~0:2ff 这段空间。
Author: Inno Fang
Link: http://innofang.github.io/2017/11/22/%E6%B1%87%E7%BC%96%E8%AF%AD%E8%A8%80%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%EF%BC%88%E4%BA%94%EF%BC%89%EF%BC%9A-BX-%E5%92%8C-loop-%E6%8C%87%E4%BB%A4/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-ND 4.0 unless stating additionally.