汇编语言复习摘要七——更灵活的定位内存地址方法

1. 以字符形式给出的数据:在汇编程序中,以'...'方式指明的数据是以字符形式给出的,编译器把它们转化为响应的ASCII码。

assume cs:code
code segment
start:
  
mov al, 'a'
  
mov bl, 'b'
  
mov ax, 4c00h
  
int 21h
code ends
end start

 

2. 大小写转换的问题:大小写字母的二进制码其实只有第5个bit(从0开始算起)是不同的,小写的字母第5个bit总是为1,而大写的总是为0. 所以,转换大小写无需判断字母是大写还是小写。and和or指令按位进行与或者或计算。下面是把字符串中的每个字符都转换成小写字母的程序:

代码
assume cs:code, ds:data
data segment
db
'BaSic'
data ends
code segment
start:
mov ax, data
mov ds, ax
mov cx, 5
mov bx, 0
s:
mov al, [bx]
or al, 00100000B
mov [bx], al
inc bx
loop s

mov ax, 4c00h
int 21h
code ends
end start

 

3. [bx + idata]:仍然表示一个内存单元,只不过这个内存单元的地址是:bx + idata;同样可以写成:

mov ax, [200 + bx]; mov ax, 200[bx]; mov ax, [bx].200

 

4. 用[bx+idata]方式进行更加灵活的数组处理:示例:假设有两个字符串,需要你在一个循环里面把这两个字符串进行这样的转换:第一个字符串全部转换成小写,第二个字符串全部转换为大写。

 

代码
assume cs:code, ds:data
data segment
db
'BaSic'
db
'fOrK'
data ends
code segment
start:
mov ax, data
mov ds, ax
mov cx, 5
mov bx, 0
s:
mov al, [0+bx]
or al, 00100000B
mov [0+bx], al
mov al, [5+bx]
and al, 11011111B
mov [5+bx], al

inc bx
loop s

mov ax, 4c00h
int 21h
code ends
end start

 

 

5. SI/DI:SI/DI 同样也是寄存器,而且跟BX功能相近,只是SI和DI不能分成两个8位的寄存器,而BX可以。

下面用SI/DI把字符串"welcome to masm!"复制到它后面的数据区里面:

 

代码
assume cs:code, ds:data
data segment
db
'welcome to masm!'
db
'................'
data ends
code segment
start:
mov ax, data
mov ds, ax
mov si, 0
mov cx, 16
s:
mov al, [0 + si]
mov [16+si], al
inc si
loop s

mov ax, 4c00h
int 21h
code ends
end start

 

 

6. [bx+si]/[bx+di] and [bx+si+idata]/[bx+di+idata]:含义类似,表示:bx+si的值/bx+si+idata的值。要注意的是,只能是bx跟si/di混合使用,不能混合使用si和di,例如:[si + di]并不合法。

 

7. 练习:将数据段中的英文字母全部改为大写,代码:

 

代码
assume cs:code, ds:data, ss:stack
stack segment
dw
0, 0, 0, 0, 0, 0, 0, 0
stack ends
data segment
db
'abc '
db
'efg '
db
'hij '
db
'klm '
data ends
code segment
start:
mov ax, data
mov ds, ax
mov ax, stack
mov ss, ax
mov sp, 16
mov cx, 4
s0:
push cx
mov si, 0
mov cx, 3
s:
mov al, [bx+si]
and al, 11011111B
mov [bx+si], al
inc si
loop s

pop cx
add bx, 6
loop s0

mov ax, 4c00h
int 21h
code ends
end start

思路:需要用到两重循环,这在高级语言中是非常简单的事情。在汇编中,循环计数只能用CX寄存器,那么两重循环势必都要用到CX的值。然而,如果没有把CX的值保存起来,那么将会造成CX的值改变了,也达不到我们的目的。所以,如何保存CX的值成为程序的关键。

 

假如把CX存在数据段中,是可以,但是你必须记住存在数据段中哪一个地址,这样势必就会造成我们程序编写上的困难。所以一般我们的方法是把临时变量存储在栈上面,这跟高级语言的道理是一样的。像C语言,我们把临时变量存储在栈上面,等到函数结束,也就销毁了临时变量。所以,我们要把CX的值存储在栈上面。在汇编中,栈空间是要自己来定义的。所以我们定义了一个16个字节长度的栈空间,用来存储CX值;要注意的是,入栈之后要出栈还给CX的值。结果如下:

 

结果
-d 13F2:0
13
F2:0000 41 42 43 20 20 20 45 46-47 20 20 20 48 49 4A 20 ABC EFG HIJ
13
F2:0010 20 20 4B 4C 4D 20 20 20-00 00 00 00 00 00 00 00 KLM ........
13
F2:0020 B8 F2 13 8E D8 B8 F1 13-8E D0 BC 10 00 B9 04 00 ................

 

8. 练习:下面我把教材中的练习题做了一次,跟上一题差不多,只是把字符串前4个改为大写而已。代码:

代码
assume cs:code, ds:data, ss:stack
stack segment
dw
0, 0, 0, 0, 0, 0, 0, 0
stack ends
data segment
db
'1. display '
db
'2. brows '
db
'3. replace '
db
'4. modify '
data ends
code segment
start:
mov ax, data
mov ds, ax
mov ax, stack
mov ss, ax
mov sp, 16

mov cx, 4
mov bx, 3
s0:
push cx
mov cx, 4
mov si, 0
s:
mov al, [bx+si]
and al, 11011111b
mov [bx+si], al
inc si
loop s

pop cx
add bx, 14
loop s0

mov ax, 4c00h
int 21h
code ends
end start

 

 

posted @ 2010-09-26 19:31  Linjian  阅读(342)  评论(0编辑  收藏  举报