[关闭]
@guoxs 2016-05-08T10:35:25.000000Z 字数 1944 阅读 3267

[BX]与loop指令

汇编语言


[BX]表示一个内存单元,他的偏移地址在bx中,段地址在ds中。
loop : 循环指令

“()” 表示一个寄存器或一个内存单元的内容,比如:
(ax) 表示ax中的内容

“()” 内的元素可以有3种类型:①寄存器名 ②段寄存器名 ③内存单元的物理地址
“(X)”所表示的数据有两种类型:①字节 ②字。是哪种类型由寄存器名或具体的运算决定。
如:(al)、(bl)、(ah)得到的数据是字节型;而(ds)、(ax)、(bx)等得到的数据是字型。

[BX]

  1. mov ax,[bx]

功能:bx中存放的数据作为一个偏移地址EA,段地址SA默认在ds中,将SA:EA处的数据送入ax中,即 (ax)= ((ds)*16 + (bx))

  1. mov [bx],ax

功能:bx中存放的数据作为一个偏移地址EA,段地址SA默认在ds中,将ax处的数据送入内存SA:EA中,即 ((ds)*16 + (bx))=(ax)

>

  1. inc bx bx中的内容加1

Loop指令

loop指令的格式是:loop标号,CPU执行loop指令的时候,要进行两步操作:
① (cx)= (cx)- 1
② 判断cx中的值,不为0则转至标号处执行程序,为0则向下执行

例子:编写2^12

  1. assume cs:code
  2. code segment
  3. mov ax,2
  4. mov cx,11
  5. s: add ax,ax
  6. loop s #s 标识一个地址,这个地址有一条指令 add ax,ax
  7. mov ax,4c00H
  8. int 21H
  9. code ends
  10. end

在debug中跟踪用loop指令实现的循环程序

在汇编程序中,数据不能以字母开头

-g 0012 : 使debug从当前的CS:IP指向的指令执行,一直到(IP)= 0012h为止。

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

  1. mov ax,[0]

这条语句在debug中表示将ds:0处的数据送入ax中,但在masm中,却被当成 mov ax,0 处理。

解决办法:
在“[]”前显式设置段寄存器。

  1. mov al,ds:[0]

loop和[bx]联合使用

问题:将 ffff:0~ffff:b中的8位数据,累加到16位寄存器dx中?

使用以为16位的寄存器ax作为中介,从而使两个运算对象的类型匹配并且结果不会超界。

  1. assume cs:code
  2. code segment
  3. mov ax,0ffffh;
  4. mov ds,ax
  5. mov bx,0 #初始化ds:bx指向ffff:0
  6. mov dx,0 #初始化累加寄存器
  7. mov cx,12 #初始化循环寄存器
  8. s: mov al,[bx]
  9. mov ah,0
  10. add dx,ax #间接向dx中加上((ds)*16 + (bx))
  11. inc bx #指向下一个单元
  12. loop s
  13. mov ax,4c00h
  14. int 21h
  15. code ends
  16. end

段前缀

可以显式的给出访问内存单元的段地址所在的寄存器,如:

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

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

编写程序安全的空间

在8086模式下,随意想一段内存空间写入内容是很为危险的,因为这段空间可能存放着重要的系统代码或指令。

在一般的PC机中,DOS方式下,DOS和其他合法的程序一般不会使用 0:200~0:2ff(00200h~002ffh)的256个字节空间。可以使用这段内存空间。

段前缀的使用

问题1:将内存ffff:0~ffff:b 单元中的数据复制到0:200~0:20b单元中。

  1. assume cs:code
  2. code segment
  3. mov ax,0ffffh
  4. mov ds,ax
  5. mov ax,0020h
  6. mov es,ax
  7. mov bx,0
  8. mov cx,12
  9. s: mov dl,[bx]
  10. mov es:[bx],dl
  11. inc bx
  12. loop s
  13. mov ax,4c00h
  14. int 21h
  15. code ends
  16. end

问题2:将“ mov ax,4c00h ”之前的指令复制到内存0:200处。

  1. assume cs:code
  2. code segment
  3. mov ax,cs #或 mov ax,code
  4. mov ds,ax
  5. mov ax,0020h
  6. mov es,ax
  7. mov bx,0
  8. mov cx,18h #或 mov cx,17h 或 sub cx,5
  9. s: mov al,[bx]
  10. mov es:[bx],al
  11. inc bx
  12. loop s
  13. mov ax,4c00h
  14. int 21h
  15. code ends
  16. end

mov 在寄存器之间传送数据的指令是2个字节,用于寄存器和立即数之间为3个字节
故有多种写法:
(1) mov ax,cs(2字节)
mov cx,17
(2) mov ax,code(3字节)
mov cx,18
(3) mov ax,cs/code
sub cx,5
因为载入时程序是,CX保存程序的长度,减去5是为了减去 mov ax,4c00h 和 int 21h 的长度

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注