汇编语言学习——第七章 更灵活定位内存地址

在这一章中,我们学习一些更灵活的定位内存地址的方法和相关的编程方法。

 

1、 两条指令and和or。

在汇编程序中,and 主要是置0, or主要是置1 。

例如:

将al的第6位设为0:and al, 10111111B

将al的第6位设为1:or al, 01000000B

 

2、 以字符的形式给出数据

在汇编程序中,用 “x”的方式指明数据是以字符的形式给出的,编译器将把它们转化为相对应的ASCII码。

如: MOV AX, 'A'   表示将‘A'的ASCII码 65赋值给AX。

 

3、大小写转换的问题

要改变一个字母的大小写,实际上就是要改变它所对应的ASCII 码。

小写字母的ASCII码值比大写字母的ASCII码值大20H (32)

大写     二进制             小写       二进制
 A         01000001          a         01100001
 B         01000010          b         01100010
 C         01000011          c         01100011
 D         01000100          d         01100100

可以看出,就ASCII码的二进制形式来看,除第5位(位数从0开始计算)外,

大写字母和小写字母的其他各位都一样。

大写字母ASCII码的第5位(位数从0开始计算)为0,小写字母的第5位为1。

也就是说一个字母,我们不管它原来是大写还是小写:

我们将它的第5位置0,它就必将变为大写字母;将它的第5 位置1,它就必将变为小写字母。

 

一道大小写转换的程序:

;大小写转换问题, BaSiC ,进行转换
ASSUME CS:CODESG, DS:DATASG

DATASG SEGMENT
DB 'BaSiC'
DATASG ENDS

CODESG SEGMENT
START:
 MOV AX, DATASG
 MOV DS, AX

 MOV BX, 0 
 MOV CX, 5
S:
 MOV AL, [BX]
 OR AL, 00100000B   ; 转换为小写
 MOV [BX],AL
 INC BX
 LOOP S

 MOV AX, 4C00H
 INT 21H
CODESG ENDS
END START

 

4、新的表示 [bx+idata]

指令mov ax,[bx+200]也可以写成如下格式(常用):

mov ax,[200+bx]

mov ax,200[bx]

[bx+idata]的方式为高级语言实现数组提供了便利机制。

 

一道例题:

; 用[bx+idata]的方式进行数组的处理
; 将datasg 定义的第一个字符串转换为大写,第二个字符串转换为小写

ASSUME CS:CODESG, DS:DATASG

DATASG SEGMENT
DB 'BaSiC'
DB 'MinIX'
DATASG ENDS

CODESG SEGMENT
START:
 MOV AX, DATASG
 MOV DS, AX
 
 MOV BX, 0
 MOV CX, 5
 
S:
 MOV AL, 0[BX]
 AND AL, 0DFH   ; 相当于 11011111B
 MOV 0[BX], AL
 
 MOV AL, 5[BX]
 OR AL, 20H
 MOV 5[BX], AL
 
 INC BX
 LOOP S


 MOV AX, 4C00H
 INT 21H
CODESG ENDS
END START


5、SI 和 DI

SI和DI是8086CPU中和bx功能相近的寄存器,但是SI和DI不能够分成两个8 位寄存器来使用

例题:

;用寄存器SI和DI实现将字符串‘welcome to masm!’复制到它后面的数据区中。

ASSUME CS:CODESG, DS:DATASG

DATASG SEGMENT
 DB 'welcome to masm!'
DATASG ENDS

CODESG SEGMENT
START:
 MOV AX, DATASG
 MOV DS, AX
 
 MOV SI,0
 MOV DI,16
 MOV CX, 16

S:
 MOV AL,[SI]
 MOV [DI], AL
 INC DI
 INC SI
 LOOP S


 MOV AX, 4C00H
 INT 21H
CODESG ENDS
END START

我很不明白: 为什么最后一个'!'复制不了??????

 

6、 不同的寻址方式的灵活应用

如果我们比较一下前面用到的几种定位内存地址的方法(可称为寻址方式),就可以发现有以下几种方式:

(1)[iata] 用一个常量来表示地址,可用于直接定位一个内存单元;

(2)[bx]用一个变量来表示内存地址,可用于间接定位一个内存单元;

(3)[bx+idata] 用一个变量和常量表示地址,可在一个起始地址的基础上用变量间接定位一个内存单元;

(4)[bx+si]用两个变量表示地址;

(5)[bx+si+idata] 用两个变量和一个常量表示地址。

 

7、书本几道例题

1); 将datasg段中的每个单词的头一个字符改为大写字母

ASSUME CS:CODESG, DS:DATASG

DATASG SEGMENT
 DB '1. file         '
 DB '2. edit         '
 DB '3. search       '
 DB '4. view         '
 DB '5. option       '
 DB '6. help         '
DATASG ENDS

CODESG SEGMENT
START:
 MOV AX, DATASG
 MOV DS, AX
 
 MOV SI, 3
 MOV CX, 6

S:
 MOV AL, [SI]
 AND AL, 0DFH
 MOV [SI],AL
 ADD SI, 16
 LOOP S
 
 MOV AX, 4C00H
 INT 21H

CODESG ENDS
END START

2); 将 datasg段中的每个单词改为大写字母

ASSUME CS:CODESG, DS:DATASG

DATASG SEGMENT
 db 'ibm             '
 db 'dec             '
 db 'dos             '
 db 'vax             '
DATASG ENDS

CODESG SEGMENT
START:
 MOV AX, DATASG
 MOV DS, AX
 
 MOV BX, 0
 MOV CX, 4
S:
 MOV SI, 0
 MOV DX, CX  ; 临时存放cx的数值
 MOV CX, 3
S1:
 MOV AL, [BX+SI]
 AND AL, 0DFH
 MOV [BX+SI],AL
 INC SI
 LOOP S1
 
 ADD BX, 16
 MOV CX, DX
 LOOP S

 MOV AX, 4C00H
 INT 21H
CODESG ENDS
END START

分析: 因为这里涉及到两重循环,而只有一个CX保存循环次数,那么意味着在进入内层循环的时候,

要先把CX暂时存放起来,内层循环执行完毕之后,再将它进行还原。本程序保存在DX中。

 

3)利用栈段存储暂时数据

; 将 datasg段中的每个单词改为大写字母,利用栈段

ASSUME CS:CODESG, DS:DATASG, SS:STACKSG

DATASG SEGMENT
 db 'ibm             '
 db 'dec             '
 db 'dos             '
 db 'vax             '
DATASG ENDS

STACKSG SEGMENT
 DW 0,0,0,0,0,0,0,0
STACKSG ENDS

CODESG SEGMENT
START:
 MOV AX, DATASG
 MOV DS, AX
 MOV AX, STACKSG
 MOV SS, AX
 MOV SP, 16 ; 栈空
 
 MOV BX, 0
 MOV CX, 4
S:
 MOV SI, 0
 PUSH CX  ;将CX进栈
 MOV CX, 3
S1:
 MOV AL, [BX+SI]
 AND AL, 0DFH
 MOV [BX+SI],AL
 INC SI
 LOOP S1
 
 ADD BX, 16
 POP CX   ; 将CX 出栈
 LOOP S

 MOV AX, 4C00H
 INT 21H
CODESG ENDS
END START

分析: 这里使用了栈来存储数据,这是一个比较好的做法,使用栈的时候,应该注意栈顶定位和栈顶越界问题。

 

4); 将datasg段中的每个单词的前四个字母改为大写字母

ASSUME CS:CODESG, DS:DATASG, SS:STACKSG

DATASG SEGMENT
 DB '1. display      '
 DB '2. brows        '
 DB '3. replace      '
 DB '4. modify       '
DATASG ENDS

STACKSG SEGMENT
 dw 0,0,0,0,0,0,0,0
STACKSG ENDS

CODESG SEGMENT
START:
 MOV AX, DATASG
 MOV DS, AX
 MOV AX, STACKSG
 MOV SS, AX
 MOV SP, 16 ; 栈为空
 
 MOV BX, 0
 MOV CX, 4
S:
 MOV SI, 3
 PUSH CX
 MOV CX, 4
S1:
 MOV AL, [BX+SI]
 AND AL, 0DFH
 MOV [BX+SI], AL
 INC SI
 LOOP S1
 
 ADD BX, 16
 POP CX
 LOOP S
 
 MOV AX, 4C00H
 INT 21H
CODESG ENDS
END START

 

以上的程序可以看出:

暂存的数据,我们可以存放在寄存器中,也可以存放在内存中。

因为寄存器的数量有限,所以我们可以将暂存的数据放到内存单元中,

需要使用的时候,再从内存单元中恢复。这样的话,我们就需要开辟一段内存空间。

 

在需要暂存数据的时候,我们都应该使用栈,这样才是一个比较好的做法。

 

个人总结: 本章的重点主要有:

1)理解and和or指令如何使某一位置1或是0

2)理解大小写的转换问题(改变大小写,其实就是改变它所对应的ASCII 码)

3)弄明白书本的几道例题(必须掌握的知识)

4) 理解栈的作用(重点)

posted @ 2013-08-19 20:31  pangbangb  阅读(367)  评论(0编辑  收藏  举报