第七章 更灵活的定位内存地址的方法
7.1 and和or指令
- and指令:逻辑与指令,按位进行与运算。
- or指令:逻辑或指令,按位进行或运算。
7.2 关于ASCII码
可以看到,在ASCII码中,用61H表示"a",41H表示"A".
7.3 以字符形式给出的数据
在汇编语言中,用’…'的方式指明数据是以字符的形式给出的,编译器将它们转化为相对应的ASCII码.
;程序7.1
assume cs:code,ds:data
data segment
db 'unIX'
db 'foRK'
data ends
code segment
start: mov al,'a'
mov bl,'b'
mov ax,4c00h
int 21h
code ends
end start
在上述程序中:
" db ‘unIX’ “相当于"db 75H,6EH,49H,58H”,因为"u",“n”,“I”,"X"对应的ASCII码为75H、6EH、49H、58H;
" db ‘foRK’ “相当于"db 66H,6FH,52H,4BH”,“f”,“o”,“R”,"K"对应的ASCII码为66H、6FH、52H、4BH;
mov al,‘a’ 相当于 mov al,61H
mov bl,'b’相当于mov bl,62H
使用Debug加载查看data段的内容:
7.4 大小写转换问题
同一个字母的大小写对应的ASCII码是不同的,二者相差20H
大写 | 十六进制 | 二进制 | 小写 | 十六进制 | 二进制 |
---|---|---|---|---|---|
A | 41 | 01000001 | a | 61 | 01100001 |
B | 42 | 01000010 | b | 62 | 01100010 |
C | 43 | 01000011 | c | 63 | 01100011 |
D | 44 | 01000100 | d | 64 | 01100100 |
E | 45 | 01000101 | e | 65 | 01100101 |
F | 46 | 01000110 | f | 66 | 01100110 |
只需将小写字母的ASCII码减去20H就可以得到大写字母,同理,将大写字母的ASCII码加上20H就可以得到小写字母。
assume cs:codesg,ds:datasg
datasg segment
db 'BaSiC'
db 'iNfOrMaTiOn'
datasg ends
codesg segment
start: mov ax,datasg
mov ds,ax
mov bx,0
mov cx,5
s: mov al,[bx]
;如果(al)>61H,则为小写字母的ASCII码,则:sub al,20H
mov [bx],al
inc bx
loop s
.
.
.
codesg ends
end start
这里的问题在于,必须先要判定字母的大小写,然后才能进行转换,这样做需要用到进行判定的指令。
但是我们能否不进行判定而直接转化呢?
重新观察ASCII码的二进制可以看出,相对应的大小写字母中,小写字母的第5位为1,大写字母的第5位为0。因此我们只需将一个字母的第五位置1,那么它就必然是小写的,置0,那么它就是大写的。
assume cs:codesg,ds:datasg
datasg segment
db 'BaSiC'
db 'iNfOrMaTiOn'
datasg ends
codesg segment
start: mov ax,datasg
mov ds,ax ;设置ds指向datasg段
mov bx,0 ;设置(bx)=0,ds:bx指向‘BaSiC’的第一个字母
mov cx,5 ;设置循环次数5,因为‘BaSiC’有5个字母
s: mov al,[bx] ;将ASCII码从ds:bx所指向的单元中取出
and al,11011111B ;将al中的ASCII码的第5位置置为0,变为大写字母
mov [bx],al ;将转变后的ASCII码写回原单元
inc bx ;(bx)加1,ds:bx指向下一个字母
loop s
mov bx,5 ;设置(bx)=5,ds:bx指向‘iNfOrMaTiOn’的第一个字母
mov cx,11 ;设置循环次数11,因为‘iNfOrMaTiOn’有11个字母
s0: mov al,[bx]
or al,00100000B ;将al中的ASCII码的第5位置置为1,变为小写字母
mov [bx],al
inc bx
loop s0
mov ax,4c00h
int 21h
codesg ends
end start
7.5 [bx+idata]
mov ax,[bx+idata]
的含义:
将一个内存单元的内容送入ax,这个内存单元的长度为2个字节,存放一个字,偏移地址为bx中的数值加上idata,段地址在ds中。
数字化的描述为(ax)=((ds)*16+(bx)+idata)
7.6 用[bx+idata]的方式进行数组的处理
在codesg中填写代码,将datasg中定义的第一个字符串转化为大写,第二个字符串转化为小写。
assume cs:codesg,ds:datasg
datasg segment
db 'BaSiC'
db 'MinIX'
datasg ends
codesg segment
start:
codesg ends
end start
按照原来的方法,用[bx]的方式定位字符串的字符。
mov ax,datasg
mov ds,ax
mov bx,0
mov cx,5
s: mov al,[bx]
and al,11011111B
mov [bx],al
inc bx
loop s
mov bx,5
mov cx,11
s0: mov al,[bx]
or al,00100000B
mov [bx],al
inc bx
loop s0
观察datasg段中的两个字符串,起始地址分别为0和5,我们可以将这两个字符串看作两个数组,一个从0地址开始存放,另一个从 5地址开始存放,使用[0+bx]和[5+bx]在同一循环中定位。
mov ax,datasg
mov ds,ax
mov bx,0
mov cx,5
s: mov al,[bx] ;定位第一个字符串中的字符
and al,11011111B
mov [bx],al
mov al,[5+bx]
or al,00100000B
mov [5+bx],al ;定位第二个字符串中的字符
inc bx
loop s
一个字符串中的字符
and al,11011111B
mov [bx],al
mov al,[5+bx]
or al,00100000B
mov [5+bx],al ;定位第二个字符串中的字符
inc bx
loop s