[BX]和loop指令

1.[bx]表示内存的用法,loop指令的用法

 

语法格式

loop 标号

通常我们用loop指令来实现循环功能,cx中存放循环次数。

cpu执行指令过程

1.cx=cx-1

2.判断cx的值是否为0

如果cx不等于0,跳转到标号出执行

如果cx=0,执行loop后面的其它指令。

2.综合应用loop和[BX]编程时,对于类型不一致(8位,16位)、数据超出范围等情形的处理(结合5.3节程序5.3和5.5节实例)

 在汇编程序中,数据不能以字母开头。例:A000h在汇编程序中要写为:0A000h

从ds中可以得到PSP的段地址SA,PSP的偏移地址为0,则物理地址为SA*16+0,可用段地址和偏移地址表示为:SA+10h:0

遇到loop指令时,可以用p指令执行,debug自动重复执行循环代码,直到(cx)=0,也可以用g命令来达到目的。

类型不一致时,例:ffff:6单元中是一个字节单元,ax是一个16位寄存器,数据长度不一样,如何赋值?

我们说的是“赋值”,就是说,让ax中的数据的值(数据的大小)和ffff:0006单元中的数据的值(数据的大小)相等。8位数据01h和16位数据0001h的数据长度不一样,但它们的值是相等的。那么我们如何赋值,设ffff:0006单元中的数据是xxh,若要ax中的值和ffff:0006单元中的相等,ax中的数据应为00xxh。所以,若实现ffff:0006单元向ax赋值,应该令(ah)=0,(al)=(ffff6h)。

有两个问题:类型的匹配和结界的不超界。具体的说,就是在做加法的时候,我们有两种方法:

1.(dx)=(dx)+内存中的8位数据;

2.(dl)=(dl)+内存中的8位数据。

第一种方法中的问题是两个运算对象的类型不匹配,第二种方法中的问题是结果有可能超界。解决这两个看似矛盾的问题,目前的方法就是得用一个16位寄存器来做中介,将内存单元中的8位数据赋值到一个16位寄存器ax中,再将ax中的数据加到dx上,从而使两个运算对象的类型匹配并且结果不会超界。

assume cs:code
code segment

         mov ax,0ffffh
         mov ds,ax
         mov bx,0   ;初始化ds:bx指向ffff:0

         mov dx,0   ;初始化累加寄存器dx,(dx)=0

         mov cx,12  ;初始化循环计数寄存器cx,(cx)=12


     s:  mov al,[bx]
         mov ah,0
         add dx,ax    ; 间接向dx中加上((ds)*16+(bx))单元的数值
         inc bx       ; ds:bx指向下一个单元
loop s mov ax,4c00h
int 21h code ends end

3.debug工具中t命令、p命令、g命令用法

 t命令

单步执行;遇loop会进入循环内部继续单步执行;遇int会进入中断程序内继续单步执行;

p命令

单步执行;遇loop或int会当作整体执行,不进入内部单步执行;

g命令

执行到指定地址;或遇程序结束或int,则终止执行。

4.debug和masm在处理内存单元上的不同及问题处理方式

 在debug中编程实现

mov ax,2000
mov ds,ax
mov al,[0]
mov bl,[1]
mov cl,[2]
mov dl,[3]

汇编源程序实现

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

 

可以看出,debug和编译器masm对形如“mov ax,[0]”这类指令在解释上的不同,debug和编译器对这些指令中的“[idata]”有不同的解释。debug将它解释为“[idata]”是一个内存单元,“idata”是内存单元的偏移地址;而编译器将“[idata]"解释为“idata”。

那么解决方法是,可将偏移地址送入bx寄存器,用[bx]的方式来访问内存单元。比如我们可以这样访问2000:0单元。

mov ax,2000h
mov ds,ax     ;段地址2000h送入ds
mov bx,0      ;偏移地址0送入bx
mov al,[bx]   ;ds:bx单元中的数据送入al
原文地址:https://www.cnblogs.com/byxy/p/10054217.html