5.《汇编语言》-王爽第三版学习笔记 [BX]和loop指令

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

  • 完整的描述一个内存单元需要两种信息:
    (1)内存单元地址
    (2)内存单元的长度(类型)
[0] 表示内存单元,它的偏移地址是 0, 段地址在 ds 中,单元的长度(类型)可以由具体指令中的其他操作对象(比如说寄存器)指出
[bx] 也表示内存单元,它的偏移地址在 bx 中,段地址在 ds 中,单元的长度(类型)可以由具体指令中的其他操作对象(比如说寄存器)指出
  1. loop
    循环指令

  2. 描述性的符号 “()”

(ax)表示ax中的内容
(al)表示al中的内容
(20000H)表示内存20000H单元的内容,其中20000H为内存单元的物理地址
  • “()” 中的元素可以由3中类型:
    (1)寄存器名
    (2)段寄存器名
    (3)内存单元的物理地址(一个20位数据)
(ax),(ds),(al),(cx),(2000H),((ds)*16 + (bx))等都是正确的用法。
(2000:0),((ds):1000H) 是不正确的用法。
(X)的应用:
(1)ax 中的内容为 0010H      =>    (ax)=0010H
(2)2000:1000H 中的内容为 0010H      =>    (21000H)=0010H
(3)mov ax,[2]      =>    (ax) = ((ds)*16+2)
(4)mov [2],(ax)      =>    ((ds)*16+2) = (ax)
(5)add ax,2      =>    (ax)=(ax)+2
(6)add ax,bx      =>    (ax)=(ax)+(bx)
(7)push ax      =>    
        (sp)=(sp)-2
        ((ss)*16+(sp))=(ax)
(8)pop ax      =>    
        (ax)=((ss)*16+(sp))
        (sp)=(sp)+2
(9)“(x)” 所表示的数据有两种各类型: 字节, 字。
       哪种类型有寄存器名或具体的运算决定。比如:
       (al)(bl)(cl)等得到的数据为字节型
       (ax)(bx)(cx)等得到的数据为字节型
       (al)=(20000H),则(20000H)得到的数据为字节型
       (ax)=(20000H),则(20000H)得到的数据为字型

5.1 [BX]

mov ax,[bx]      =>    (ax) = ((ds)*16+(bx))
mov [bx],ax      =>     ((ds)*16+(bx)) = (ax)
  • inc bx 的含义是 bx的内容 加1
mov bx,1
inc bx
// 执行后,(bx) = 2

5.2 Loop 指令
(1)格式: loop 标号

CPU在执行loop 的时候要进行两部操作:
(1)(cx)=(cx)-1
(2)判断 cx 中的值,不为0则转至 标号 处执行程序,如果为 0 则乡下执行。
注意:
     cx 中的值影响着 loop 指令的执行结果,通常(注意,说的是通常)我们用loop指令来实现循环功能,cx中存放循环次数。
  • example1: 编程计算 2^11,结果存在 ax 中
assume cs:code
code segment
    mov ax,2
    .... //重复累计做11次 add ax,ax

    mov ax,4c00h
    int 21h
code ends
end
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) 标号: 汇编语言中,标号代表一个地址,程序中有一个标号 s, 它实际上标识了一个地址,这个地址处有一条指令:add ax,ax
* (2) loop s : CPU 执行 loop s 的时候,需要进行两步操作:
        第一步: (cx)=(cx)-1
        第二步:判断 cx 中的值,不为 0,则转至标号 s 所标识的地址处执行(程序中的指令是 add ax,ax),如果为 0 则执行下一条指令(下一条指令是 mov ax,4c00h)
*/
  • cx 和 loop 指令相配合实现循环功能的 3 个要点:
(1)在 cx 中存放循环次数
(2)loop 指令中的标号所标识的地址要在前面
(3)要循环执行的程序段,要写在 标号 和 loop 指令的中间
  • cx 和 loop 指令相配合实现循环功能的 程序框架:
    mov cx,循环次数
s:  
    循环执行的程序段
    loop s

5.3 DEBUG中 跟踪 loop 指令实现循环程序

  • 汇编程序中,数据不能以字母开头。
    所以前面要加 0 。 比如 mov ax,0FFFFH
  • g 0012 => 表示 CS:0012 前的程序被执行。
  • 遇到 loop 指令时,使用 p 命令执行, Debug 就会自动重复执行循环中的指令,知道 (cx)= 0 为止。

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


89D5AE61-5605-4C5F-BA87-AAD7563A04BD.png

E60D272C-E906-4175-944F-DD044D68DE03.png
  • Debug 和 编译器 对 “ mov al,[0] ” 的解释不同,debug 中 认为 [0] -> ((ds)*16 + 0) 即 内存单元, 编译器则解释为 常量 0
汇编源程序中一下指令的含义:
mov al,[0]  =>  (al)=0 ,将常量0送入al中 等同于 mov al,0
mov al,ds:[0]  =>  (al)=((ds)*16+0) ,将内存单元中的数据送入al中
mov al,[bx]  =>  (al)=((ds)*16+bx)  ,将内存单元中的数据送入al中
mov al,ds:[bx]  =>  等同于 mov al,[bx]
  • 在汇编源程序中, 如果用指令访问一个内存单元,则在指令中必须用“ [...] ” 来表示内存单元, 如果 “ [] ” 中用的是一个常量 idata,直接给成内存单元地址,就要在 “ [] ” 的前面显式的给出 段地址所在的段寄存器。 比如
    mov al,ds:[0]
  • 如果 “ [] ” 里用寄存器 如 mov al,[bx], 间接给出内存单元的偏移地址,则段地址默认在ds中。当然,也可以显式的给出段地址所在的段寄存器。

5.5 loop 和 [bx] 的联合应用
计算 ffff:0~ffff:b 单元中数据的和,结果存储在 dx 中

assume cs:code
code segment
    mov ax,0ffffh
    mov ds,ax
    mov bx,0
    mov dx,0
    mov cx,12

s:  mov al,[bx]
    mov ah,0
    add dx,ax
    inc bx
    loop s

    mov ax,4c00h
    int 21h

code ends
end

5.6 段前缀 : 出现在访问内存单元的指令中,用于显式的指明内存单元的段地址。

(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 中。
(5)mov ax,ss:[0]  //将一个内存单元的内容送入 ax,这个内存单元的长度为 2字节(字单元),存放一个字, 偏移地址 0,段地址在 ss 中。
(6)mov ax,cs:[0]  //将一个内存单元的内容送入 ax,这个内存单元的长度为 2字节(字单元),存放一个字, 偏移地址 0,段地址在 cs 中。

5.7 一段安全的空间:
0:200 ~ 0:2FF

5.7 段前缀的使用:
将 内存 ffff:0 ~ ffff:b 单元中的数据复制到 0:200 ~ 0:20B 单元中

assume cs:code
code segment
    mov bx,0
    mov cx,12

s:  mov ax,0ffffh
    mov ds,ax
    mov dl,[bx]

    mov ax,0020h
    mov ds,ax
    mov [bx],dl

    inc bx
    loops

    mov ax,4c00h
    int 21h
code ends
end
  • 练习
    (1)编程, 向内存 0:200~0:23F 一次传送数据 0~63?
assume cs:code
code segment
    mov ax,0020h
    mov ds,ax
    mov bx,0
    mov cx,64

s:  mov [bx],bx
    inc bx
    loop s

    mov ax,4c00h
    int 21h
code ends
end

(2)下面的程序的功能是将“mov ax,4c00h”之前的指令复制到内存0:200处,补全程序。上机调试,跟踪运行结果。

assume cs:code
code segment
    mov ax,code
    mov ds,ax
    mov ax,0020h
    mov es,ax
    mov bx,0
    mov cx,17h

s:  mov al,[bx]
    mov es:[bx]:al
    inc bx
    loop s

    mov ax,4c00h
    int 21h
code ends
end
B82070D5-D1F5-413B-B891-9445AAD63755.png

你可能感兴趣的:(5.《汇编语言》-王爽第三版学习笔记 [BX]和loop指令)