汇编语言[王爽]-05 [BX]和loop指令

loop指令实现循环

执行过程:

①(cx)=(cx)-1

②判断 cx 中的值,不为零则转至标号处执行程序,如果为零则向下执行。

例:计算2^12

assume cs:codeseg

codeseg segment

	mov ax,2
	#-------做11次add ax,ax----------
	mov cx,11
s:
	add ax,ax
	loop s
	#--------------------------------
	mov ax,4c00h
	int 21h

codeseg ends
end

框架

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

考虑这么一个问题:计算ffff:0006单元中的数乘以3,结果储存在dx中

分析:

  1. 结果不能储存在一个8位的寄存器中,存在越界的可能,存在16位的寄存器中显然则不会越界,所以需要存在dx中而不是dl或者dh
  2. 基本思路:dx=0,把(ffff:0006)中的字节型数据放入ax中,执行三次add dx,ax
  3. 八位的内存单元如何给16位的ax赋值? 令(ah)=0,赋值给al
assume cs:code
code segment
	mov ax,0ffffh
	mov ds,ax
	mov bx,6h

	mov ah,0
	mov al,[bx]

	mov dx,0
	mov cx,3
s:
	add dx,ax
	loop s

	mov ax,4c00h
	int 21h
code ends
end

当写入 mov al,[dx] 时,编译器报错

Untitled

debug调试循环的方式

g ip地址 : 直接执行到某条指令

p : 可以用来结束int 21h,也可以用来跳过循环

注:debug调试程序时,文件名要带上后缀 -debug p.exe

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

mov ax,[0]

Debug解释为 mov ax,((ds)*16+0)

masm解释为 mov ax,0

所以在masm要写为

# 显示指明段前缀
mov ax,ds:[0]

# 用寄存器
mov bx,0
mov ax,[bx]

loop 和 [bx]的联合运用

考虑这样一个问题,计算ffff:0 ~ ffff:b 单元中的数据的和,结果储存在bx中

8位数据存入al,以ax为中转赋值给bx【bx不会越界进位】

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
s:
	mov ah,0
	mov al,ds:[bx]	;ax为中介传递数据
	add dx,ax
	inc bx			;ds:bx指向下一个元素
	loop s

	mov ax,4c00h
	int 21h
code ends
end

一段安全的空间

assume cs:code
code segment
	mov ax,0
	mov ds,ax
	mov ds:[26h],ax

	mov ax,4c00h
	int 21h
code ends
end

执行上述的程序,系统会死机

因为在实模式下,我们可以自由地操纵真实的硬件;

在保护模式下,则是在操作系统的保护下,无法操纵真实的硬件

所以在实模式下编程时,要使用安全的内存空间

一般是 0:200 ~ 0:2ff 这256字节的空间

段前缀的使用

考虑一个问题,把内存ffff:0 ~ ffff:b中的数据复制到 0:200 ~ 0:20b中

assume cs:code
code segment
	;设置两个段前缀
	mov ax,0ffffh
	mov ds,ax

	mov ax,20h
	mov es,ax

	mov bx,0
	mov cx,12
s:
	mov dl,ds:[bx]
	mov es:[bx],dl
	inc bx
	loop s

	mov ax,4c00h
	int 21h
code ends
end

为什么要使用 dl 而不是 mov es:[bx], ds:[bx]

因为 直接mov的话,没有指定内存大小,会报错

Untitled

其实可以用 dx 但是那样的话 bx就不是 inc 而是 add bx,2

实验四 [bx]和loop的使用

第四章 第一个程序

posted @ 2025-09-15 16:03  Miaops  阅读(5)  评论(0)    收藏  举报