汇编语言王爽第四版 实验四(包括对【bx】,loop详解)

基本概念

汇编语言所有的实验地址

  1. [bx]与内存单元
[bx]与[0]类似,[0]表示的是内存单元,偏移地址是[0],段地址默认是ds
例子:mov ax,[0]    ->将一个内存单元的内容送进ax(内存单元长度为2字节,这主要取决于ax是存放2字节的)
	 mov al,[0]    ->将一个内存单元的内容送进al(内存单元长度为1字节,这主要取决于al是存放1字节的)
	 上面的段地址都是默认取ds中的,偏移地址取[0]中
	
    mov ax,[bx]    ->同上,只不过偏移地址是存放于[bx]中
    mov al,[bx]    ->同上,只不过偏移地址是存放于[bx]中
  1. loop
循环的意思,我们在实验一中求2^8就是利用了循环
  1. 描述性符号"()"
()用来表示一个寄存器或者内存单元的内容
(ax)表示ax的内容,(20000H)表示20000H单元的内容
内存单元的地址都是物理地址
()中的元素可以是1.寄存器名2.段寄存器名3.内存单元的物理地址
不能是例如(2000:0)这样的(段地址:偏移地址的形式),如果想描述可以是((ds)*16+(bx))
  1. 约定符号idata表示常量

[BX]

mov ax,[bx]
由上面的描述可以知道 指令的意思是(ax) = ((ds) * 16 + (bx))    ->bx是偏移地址,ds是默认的段地址

Loop指令

loop 指令的格式:loop 标号
CPU执行loop指令:1.(cx) = (cx) - 1
			    2.判断cx的值是否为0,为零就退出循环
框架:
	mov cx,循环次数
s:
	循环执行的程序段
	loop s
其实总的来说跟while(num--){执行程序}循环差不多,num就是循环次数,每次减一,不为零就执行程序
举例:
	用加法计算123*236,结果存放在ax中
分析:用加法计算就是讲123加236次
	assume cs:code
	code segment
		mov ax,0
		mov cx,236
	s:
    	add ax,123
    	loop s
    	
    	mov ax,4c00h
    	int 21h
    code ends
    end

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

计算ffff:0006单元中的数乘以3,结果存储在dx中
assume cs:code
code segment
	mov ax,0ffffh	;汇编数据不能以字母开头,因此加入前缀0
	mov ds,ax
	mov bx,6
	
	mov al,[bx]
	mov ah,0
	
	mov dx,0
	
	mov cx,3 		;设置循环次数
s:  add dx,ax
	loop s
	mov ax, 4c00h
	int 21h
code ends
end


按照书本上的一步步走就行了

Debug :g 指令

当我们在Debug中想要追踪某一个特定的程序段,而不想追踪前面的程序段,我们可以使用 g指令
例如:我们想从cs:0012位置开始追踪 ->  g 0012
执行上述指令后,从cs:ip位置开始执行到cs:0012位置停止,然后等待你的命令。。。

Debug : p 命令

当我们希望循环一次性的执行完毕我们总不能一直按t吧,可以用p指令进行执行循环
当我们遇到loop指令时使用p指令就可以一次性执行完循环

Debug和masm对指令的不同处理

二者的区别主要是对于【idata】的解释
在Debug中 mov al,[0]表示的是将ds:0中的数据送入到ax中
而在汇编源程序中解释为:将数据0送入到ax中

那么我们在源程序中应该如何ds:0中的内容送到ax中呢?
1.可以用[bx]作为过渡的寄存器
mov ax,2000h
mov ds,ax
mov bx,0
mov al,[bx]
2.在[0]的前面显示的加上段地址
mov ax,2000
mov ds,ax
mov al,ds:[0]

loop和【bx】的联合应用

问题:计算ffff:0 到 ffff:b单元中数据的和,结果存储在dx中

分析:能否直接将ffff:0~ffff:b的数据直接累加呢?不行,因为数据是8位的,不能直接累加到16位的寄存器dx中

能否累加数据到dl中,(dh)设置为0呢?不行,12个8位的数据累加到8位的寄存器可能会造成进位的丢失

解决方法:

​ 1.用一个16位的寄存器作为过渡,然后将16位的数据依次累计到dx中

代码如下:

assume cs:code 
code segment 
	mov ax,0fffffh		;数据首位不能是字母开头,因此前面加上一个前缀0
	mov ds,ax
	mov bx,0			;bx代表了偏移地址
	mov dx,0		
	mov cx,12			;一共循环12次
	
s:  mov al,[bx]
	mov ah,0
	add dx,ax
	inc bx				;bx加1
	loop s				;循环

	mov ax,4c00h
	int 21h
code ends
end

段前缀

就是出现在访问地址单元中,用于显示的指明内存单元的段地址的例如“ds: ” "cs:"等就是段前缀

一段安全的空间

  • 我们需要直接向一段内存中写入内容
  • 这段内存中不应该存放系统或者其他程序的代码或者是数据
  • Dos方式下,一般0:200~0:2ff空间中没有系统或者其他程序的数据和代码
  • 向内存中写入内容时,使用0:200~0:2ff这一段空间

段前缀的使用

将内存中ffff:0ffff:b单元中的数据复制到0:200020b(等同于0020:0~0020:b)中

我们循环的将f…中的数据存到dl中(一个字节的单位就行),然后将dl转存到0020:…中

assume cs:code
code segment 
	mov bx,0
	mov cx,12		;循环12次

S:	mov ax,0ffffh
	mov ds,ax
	mov dl,[bx]			;此时将原内存中的一个单元数据放到了dl中了
	
	mov ax,0020h
	mov ds,ax			;更换ds的存储的是目标内存的段地址了
	mov [bx],dl			;将dl中的内容转存到目标内存中
	
	inc bx				;bx指针加一
	loop s


code ends
end

可以再加一个段前缀使得代码更加的简洁

assume cs:code
code segment
	
	mov ax,0ffffh
	mov ds,ax
	
	mov ax,0200h
	mov es,ax
	
	mov bx,0
	
	mov cx,12

s:  mov dl,[bx]		;将ds:bx中的存到dl中
	mov es:[bx],dl
	
	inc bx
	loop s
	
	mov ax,4c00h
	int 21h

code ends
end

实验四:【bx】和 loop的使用

  1. 向内存0:200~0:23F 依次传送数据 0~63(3FH)

    分析一哈:跟上面的问题类似,我们一共需要传送64次数据(从0 - 63) 每次用8位的寄存器进行中转就行了

    😃

assume cs:code 
code segment 

	mov ax,0
	mov ds,ax		;段数据是0
	mov cx,64		;64次循环
	mov bx,200h
	mov al,0
	
s:	mov [bx],al
	inc bx			;bx加一
	inc al			;数值加一

loop s
	
	mov ax,4c00h
	int 21h
	
code ends
end

我们编译链接执行后debug看一下0:200的内存

在这里插入图片描述

发现内存的确是从0-63(0-3F)进行填充,不熟悉编译链接debug的可以查看我上一篇文章,有详细的步骤

  1. 向内存0:2000:23F依次传入数据063(0~3FH),程序中只能用9条指令,包括mov ax,4c00h和int 21h
assume cs:code

code segment

	mov bx,0h
	mov ds,bx
	mov ax,200h
	mov cx,64
	
s:  mov [bx+200h],bx
	inc bx
	loop s
	
	mov ax,4c00h
	int 21h

code ends
end

结果不再演示了,你可以自己debug看一下

  1. 补全下面的程序,其功能是将mov ax,4c00之前的指令复制到内存0:200处,补全程序,上机调试,跟踪运行结果

    提示:

    1. 复制了什么?从哪里到哪里?
    2. 复制的是什么?有多少字节,你如何知道要复制的字节数量?

我们复制的是指令,指令存放在cs:ip中,所以第一个空应该填cs

第二个空填写17,可以在执行前查看一下占用的字节数

assume cs:code
code segment

	mov ax,cs
	mov ds,ax
	mov ax,0020h
	mov es,ax
	mov bx,0
	mov cx,23
s:  mov al,[bx]
	mov es:[bx],al
	inc bx
	loop s
	
	mov ax,4c00h
	int 21h
code ends
end

我们执行完毕之后,用debug查看一下

在这里插入图片描述

  • 23
    点赞
  • 132
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
第1章 基础知识   1.1 机器语言   1.2 汇编语言的产生   1.3 汇编语言的组成   1.4 存储器   1.5 指令和数据   1.6 存储单元   1.7 CPU对存储器的读写   1.8 地址总线   1.9 数据总线   1.10 控制总线   1.11 内存地址空间(概述)   1.12 主板   1.13 接口卡   1.14 各类存储器芯片   1.15 内存地址空间  第2章 寄存器  2.1 通用寄存器         2.2 字在寄存器中的存储     2.3 几条汇编指令        2.4 物理地址          2.5 16位结构的CPU       2.6 8086cPu给出物理地址的方法 2.7 “段地址xl6+偏移地址=物理地址”的本质含义         2.8 段的概念          2.9 段寄存器          2.10 CS和IP          2.11 修改CS、IP的指令     2.12 代码段          实验1 查看CPU和内存,用机器指令和汇编指令编程    第3章 寄存器(内存访问)    3.1 内存中字的存储      3.2 DS 31:1[address]         3.3 字的传送         3.4 ITIOV、add、sub指令    3.5 数据段          3.6 栈                3.7 CPU提供的栈机制     3.8 栈顶超界的问题       3.9 puSh、pop指令       3.10 栈段           实验2 用机器指令和汇编指令编程  第4章 第一个程序          4.1 一个源程序从写出到执行的过程  4.2 源程序             4.3 编辑源程序           4.4 编译              4.5 连接              4.6 以简化的方式进行编译和连接   4.7 1.exe的执行           4.8 谁将可执行文件中的程序装载进入内存并使它运行?        4.9 程序执行过程的跟踪       实验3 编程、编译、连接、跟踪   第5章 【BX】和loop指令       5.1 【BX】              5.2 Loop指令            5.3 在Debu9中跟踪用loop指令实现酮循环程序            5.4 Debu9和汇编编译器masm对指令的不同处理         5.5 loop和【bx】的联合应用     …… 第3章 寄存器(内存访问)  第4章 第一个程序  第5章 [BX]和loop指令  第6章 包含多个段的程序  第7章 更灵活的定位内存地址的方法  第8章 数据处理的两个基本问题  第9章 转移指令的原理  第10章 CALL和RET指令  第11章 标志寄存器  第12章 内中断  第13章 int指令  第14章 端口  第15章 外中断  第16章 直接定址表  第17章 使用BIOS进行键盘输入和磁盘读写  综合研究  附注

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值