汇编语言(王爽)第五章

第五章

预备知识

[bx]同样表示一个内存单元,偏移地址在bx中,段地址在ds中

我们用描述性的符号()来表示一个寄存器或一个内存单元中的内容

(ax)表示ax中的内容,(20000H)表示内存20000H单元的内容

((ds)*16+(bx)),ds中的内容为ADR1,bx中的内容为ADR2,所以表示ADR1:ADR2单元的内容

(2000:0)、((ds):1000H)是不正确的用法

一些具体应用

mov ax,[2]可以描述为(ax)=((ds)*16+2)

push ax可以描述为 (sp)=(sp)-2 ((ss)*16+(sp))=(ax)

(X)所表示的数据有两种类型:字节或者字,是哪种类型由寄存器名或具体的运算决定

(al) (bl)为字节型 (ds) (ax)为字型

扫描二维码关注公众号,回复: 9629081 查看本文章

5.1 [BX]

inc bx	;bx自增
mov [bx],ax	;传入一个字,[bx]后一个单元也被赋值
mov [bx],al	;传入一个字节

5.2 Loop指令

CPU执行loop指令的时候,先(cx)=(cx)-1,再判断cx中的值,不为零则转至标号处执行程序,为零则向下执行,所以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

循环框架如下

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

实现用加法计算123*236,一种是123加236次,另一种是235加123次,显然后者更快

assume cs:code
code segment

	mov ax,0
	mov cx,123
  s:add ax,236
    loop s
    
    mov ax,4c00H
    int 21H
code ends
end

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

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

1、运算的结果是否会超出dx所能存储的范围?

255*3 < 65535 不会

2、将ffff:0006单元中的数值赋给ax,用dx做3次(dx)=(dx)+(ax),但ffff:6是一个字节单元,ax是16位的寄存器,长度不一样,如何赋值?

如果mov ax,[6] 赋值时ffff:0006中的内容会传到ax的低位,而ffff:0007中的内容会传到ax的高位,为了使ax中数值大小上=与ffff:0006单元上的数值大小相同,我们设法使ah=0

assume cs:code
code segment
	mov ax,0ffffH
	mov ds,ax
	mov bx,6	;ds:bx
	
	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

注意第一条指令,在汇编源程序中,数据不能以字母开头,所以要在前面加0,A000H在汇编源程序中写为0A000H

在Debug中,loop s会变为loop s所指的地址,如loop 0012

假设循环程序段从CS:0012开始,之前的代码不想一步步执行,可以使用g 0012,Debug从当前CS:IP指向的指令开始,一直到(IP)=0012H

如果循环次数过多,可以在再次遇到loop指令时使用p命令,自动执行剩下的循环,直到cx为0,也可以用g 1006(假设CS:1006为loop指令下一条指令的地址)

5.4 Debug和masm对指令的不同处理

在Debug写指令mov ax,[0],表示将ds:0处的数据送入ax,但在汇编源程序中,指令mov ax,[0]被编译器当作指令mov ax,0处理,因此,如果要将2000:0单元中的数据送入al,用[bx]的方式来访问内存单元

mov ax,2000H
mov ds,ax
mov bx,0
mov al,[bx]

但这样十分麻烦,因此我们采取显示地给出段地址所在的段寄存器的方法

mov ax,2000H
mov ds,ax
mov al,ds:[0]

总结:[…]中为常量idata,前面需要显示地给出段寄存器,否则masm将[idata]解释为idata,如果[…]中为寄存器,则段地址默认在ds中,当然也可以显示得给出段地址所在的段寄存器

5.5 loop和[bx]的联合应用

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

运算结果不会超出dx的存储范围,但是不能将ffff:0~ffff:b中的数据直接累加到dx中,因为前者的数据是8位的,长度不匹配,但如果累加到dl中,(dh)=0,很可能造成进位损失,所以用一个16位寄存器来做中介

assume cs:code
code segment

	mov ax,0ffffH
	mov ds,ax
	mov bx,0
	
	mov dx,0
	
	mov cx,12	;0~b 一共12次
	
  s:mov al,[bx]
    mov ah,0
    add dx,ax
    inc bx
    loop s
    
    mov ax,4c00H
    int 21H
code ends
end

5.6 段前缀

mov ax,ds:[bx]
mov ax,cs:[bx]
mov ax,ss:[bx]
mov ax,es:[bx]
mov ax,ss:[0]
mov ax,cs:[0]

ds: cs: ss: es: 在汇编语言中称为段前缀

5.7 一段安全的空间

在8086模式中,随意向一段内存空间写入内存是很危险的,可能这段内存中有重要的数据或代码

如果我们需要向内存空间写入数据的话,要使用操作系统给我们分配的空间

DOS方式下,一般0:200~0:2ff空间中没有系统或其他程序的数据或代码,在需要向内存中写入数据时,就使用这段空间

5.8 段前缀的使用

将内存ffff:0·ffff:b单元中的数据复制到0:200~0: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
发布了84 篇原创文章 · 获赞 7 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_43569916/article/details/104503782
今日推荐