7.更灵活的定位内存地址的方法
[toc]
前面用过直接寻址 [0]和间接寻址[bx]
and 和 or指令
就是按位与 按位或。
and ax, 0111h
(ax) = (ax) and 0111h
or ax, 0111h
(ax) = (ax) or 0111h
关于ASCII码
我记得以前有个同事说过一个问题:
声明编码为utf8 和 gbk, 你怎么识别呢?
譬如美国人说我说的英语。。中国人说我说的中国话。两个人互相听不懂对方的话,有啥意义?
这里他就是没理解ASCII码。 在所有编码中ASCII码都是一样的,可以说是通用语。所以声明编码是有意义的。
这里简单拓展下utf8编码。
utf8是一种变成字节编码方式。有的字符用1个字节表示,有的字符用2个字节表示,有的字节用3个字节表示。那么你怎么去解析呢?
有规则:
1字节 以0开头。。这里也就是ASCII码。。。所以说utf8中的ascii码 表示 和ascii码是一样的。
2字节 110xxx 10xxx
3字节 1110xxx 10xxx 10xxx
当按这个规则解析异常时,就表示解析失败。譬如解析时遇到111011011 10xxx 1110xxx 这就有问题了,第三个字节应该是10开头才对。
这种不能识别的字节,会被转成三个字节{11101111,10111111,10111101}, 也就是239,191,189
以字符形式给出的数据
在汇编程序中可以用’…'的方式指明数据是以字符的形式提供的,这样编译器会把他们转成相应的ASCII码。
如
assume cs:code, ds:data
data segment
db 'unIX'; db = define byte, 相当于 db 75H, 6EH, 49H, 58H 谁会去记具体的ASCII码,难记也难写。
db 'foRk'
data ends
code segment
start: mov al, 'a'
mov bl, 'b'
mov ax, 4c00h
int 21h
cod ends
end start
大小写转换的问题
就是利用一个规律。
字母 and 1101111B = 大写字母
字母 or 00100000B = 小写字母
[bx+idata]
除了 mov ax, [0]
mov ax,[bx]
这样常量,变量的形式,还支持常量+变量的方式。
mov ax,[bx+200]
表示 (ax) =( (ds)*16+(bx)+200)
其他形式还有:
mov ax, [200+bx]
mov ax, 200[bx]
mov ax, [bx].200
用[bx+idata]的方式进行数组的处理
把大小写转换程序 改用数组实现
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,[bx] ; 一个字符只占一个字节,所以得用al
add al, 11011111b; 这里是转大写
mov [bx], al ; 转换完,放回去
mov al,[5+bx]
or al, 00100000b
mov [bx],al
inc bx
loop s
mov ax, 4c00h
int 21h
codesg ends
end start
SI和DI
si和di是8086CPU中 和 bx功能相近的寄存器,不过他不能分成两个 8位寄存器来使用。
[bx+si]和[bx+di]
就是2个变量组合了。
之前有常量,变量,常量+变量。这就是变量+变量。
mov ax, [bx+si]
(ax) =( (ds)*16 + (bx)+(si))
[bx+si+idata]和[bx+di+idata]
内存寻址,变量+变量+常量。
不同的寻址方式的灵活应用
寻址总结:
- [idata], 常量,直接寻址。
- [bx], 变量,间接寻址。
- [bx+idata] 变量+常量
- [bx+si] 2个变量
- [bx+si+idata] 2个变量+常量
一般来说,在需要暂存数据的时候,我们都应该使用栈。