基本概念

汇编语言所有的实验地址

  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查看一下

在这里插入图片描述

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐