学习笔记 -- [BX]和loop

[bx]

描述一个内存单元,需要两种信息:

  1. 内存单元的地址
  2. 内存单元的长度(类型)

用[0]表示一个内存单元时,0表示单元的偏移地址,段地址默认在ds中,单元长度由具体指令中的其他操作对象指出。

[bx]同样也表示一个内存单元,它的偏移地址在bx中。

mov ax,[bx]

功能:bx中存放的数据作为一个偏移地址EA,段地址SA在ds中,将SA:EA处的数据送入ax。

mov [bx],ax

功能:bx中存放的数据作为偏移地址EA,段地址SA在ds中,将ax中的数据送入内存SA:EA处。

存入字节数据就bx一个单元的数据,字型数据要bx和bx+1两个内存单元的数据。

注:( )表示一个寄存器或一个单元的内容,(ax)表示ax寄存器里的值。

Loop指令

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

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

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

计算2^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

cx和loop指令实现想你换功能的要点:

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

cx和loop指令的程序框架

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

Debug 和masm对指令的不同处理

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

在Debug中,

mov ax,[0]

表示将ds:0处的数据送入ax中。

在汇编源程序中,

mov ax,[0]

被当作mov ax,0 处理。

可以将偏移地址送入bx寄存器中,用[bx]的方式来访问内存单元。

mov ax,1200h
mov ds,ax
mov bx,0
mov al,[bx]

汇编源程序指令的含义。

mov 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] 相同

在汇编源程序中,如果用指令访问一个内存单元,则指令中必须用[…]来表示内存单元,如果[ ]里用过一个常量x给出内存单元的偏移地址,就要在[ ]前面给出段地址所在的段寄存器。

mov al,ds:[0]

如果没有在[ ]前面给出段地址所在的寄存器。

mov al,[0]

masm将把指令中的[0]解释为0。

如果在[ ]里用寄存器,比如bx,间接给出内存单元的偏移地址,则段地址默认在ds中。

loop和[bx]的联合应用

假如要把字节型数据存放到16位寄存器dx中,存在两个问题:类型的匹配和结果的不超界。方法:

  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 dx,0
	mov al,ds:[0]
	mov ah,0
	add dx,ax
	……
	mov ax,4c00h
	int 21h
code ends
end

这样的代码就需要手动的把[0]、[1]…[0bh]中的数据赋值给al。

将偏移地址设成变量会方便许多,这个变量将通过bx的改变来实现。

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

bx可以看作一个代表内存单元地址的变量,可以不用写新的指令,仅通过改变bx中的数值,改变指令访问的内存单元。

段前缀

mov ax,[bx]

内存单元的偏移地址由bx给出,而段地址默认在ds中。也可以在内存单元的指令中给出内存单元的段地址所在的段寄存器。

mov ax,ds:[bx]
mov ax,cs:[bx]	段地址在cs中,偏移地址在bx中
mov ax,ss:[bx]	段地址在ss中,偏移地址在bx中
mov ax,es:[bx]	段地址在es中,偏移地址在bx中

用于显式地知名内存单元的段地址的ds: cs: ss: es: ,被称为段前缀。

安全的空间

随意向一段内存空间写入内容是很危险的,因为这段空间中可能存放着重要的系统数据或代码。随意改写可能会引发错误。

进入DOS后,可以先用Debug查看一下,内存单元内容都是0的话,这段空间就是安全的。

段前缀的使用

假如要将内存ffff:0ffff:b单元中的数据复制到0:2000:20b单元中,就可以用到段前缀来简化代码。

assume cs:code
code segment
		mov ax,0ffffh
		mov ds,ax
		mov ax,0020h
		mov es,ax
		mov bx,0
		mov cx,12
s:		mov dl,[bx]
		mov es:[bx],dl
		inc bx
		loop s
		mov ax,4c00h
		int 21h
code ends
end

ds中存放源始空间的段地址,es存放目标空间的段地址。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值