前言
参考书籍:
王爽。汇编语言。北京:清华大学出版社, 2013:138-160
本人菜狗一枚,不敢咬文嚼字,只能站在巨人的肩膀上窥探一下未曾了解的世界。
and 和 or 指令
-
and 指令:逻辑与指令,按位进行与运算
mov al, 0000 0101B and al, 0000 0110B ; ax = 0000 0000B
通过该指令可将操作对象的相应位设为 0,其余位不变。
-
or 指令:逻辑或指令,按位进行或运算
mov al, 0000 0101B or al, 0000 0110B ; ax = 0000 0111B
通过该指令可将操作对象的相应位设为 1,其余位不变。
操作对象 | 指令 | 数值 | 结果 |
---|---|---|---|
1 | and | 1 | 1 |
1 | and | 0 | 0 |
0 | and | 1 | 0 |
0 | and | 0 | 0 |
1 | or | 1 | 1 |
1 | or | 0 | 1 |
0 | or | 1 | 1 |
0 | or | 0 | 0 |
以字符形式给出的数据
assume cs:code, ds:data
; db 'unIX' 相当于 db 75H, 64H, 49H, 58H
; db 'foRK' 相当于 db 66H, 6FH, 52H, 4BH
data segment
db 'unIX'
db 'foRK'
data ends
; mov al, 'a' 相当于 mov al, 61H, 'a' 的 ASCII 码为 61H
; mov bl, 'b' 相当于 mov bl, 62H, 'b' 的 ASCII 码为 62H
code segment
start:
mov al, 'a'
mov bl, 'b'
mov ax, 4c00h
int 21h
code ends
end start
大小写转换的问题
大写 | 十六进制 | 二进制 | 小写 | 十六进制 | 二进制 | |
---|---|---|---|---|---|---|
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 码的二进制形式来看,除第 5 位(位数从 0 开始计算)外,大写字母和小写字母的其他各位都一样。大写字母 ASCII 码的第 5 位为 0,小写字母的第 5 位为 1。所以一个字母,不管它原来是大写还是小写,将它的第 5 位置 0,它就必将变为大写字母;将它的第 5 位置 1,它就必将变为小写字母。
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]
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
mov ax, 4c00h
int 21h
codesg ends
end start
[bx+idata]
[bx+idata] 表示一个内存单元,它的偏移地址为 (bx) +idata(bx 中的数值加上 idata)。
指令:mov ax, [bx+200]
数学描述:(ax) = ((ds) * 16 + (bx) + 200)
含义:将一个内存单元的内容送入 ax,这个内存单元的长度为 2 个字节(字单元),存放一个字,偏移地址为 bx 中的数值加上 200,段地址在 ds 中。
常用格式:
- mov ax, [bx+200]
- mov ax, [200+bx]
- mov ax, 200[bx]
- mov ax, [bx].200
设一段内存为 2000:1000 BE 00 06 00 00 00 …
对于 ds 为 2000,bx 为 0 有
汇编指令 | 执行结果(ax) |
---|---|
mov ax, [bx] | 00BEH |
mov ax, [bx+1] | 0600H |
mov ax, [bx+2] | 0006H |
用 [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]
and al, 11011111b
mov [bx], al
mov al, [5+bx]
or al, 00100000b
mov [5+bx], al
inc bx
loop s
mov ax, 4c00h
int 21h
codesg ends
end start
datasg 段中的两个字符串,一个起始地址为 0,另一个起始地址为 5。将这两个字符串看作两个数组,一个从 0 地址开始存放,另一个从 5 开始存放,即可以用 [0+bx] 和 [5+bx] 的方式在同一个循环中定位这两个字符串中的字符。0 和 5 给出了两个字符串的起始偏移地址,bx 中给出了从起始偏移地址开始的相对地址。
SI 和 DI
si 和 di 是 8086CPU 中和 bx 功能相近的寄存器。
si 和 di 不能够分成两个 8 位寄存器来使用。
assume cs:codesg, ds:datasg
datasg segment
db 'welcome to masm!'
db '................'
datasg ends
codesg segment
start:
mov ax, datasg
mov ds, ax
mov si, 0
mov di, 16
mov cx, 8
s:
mov ax, [si]
mov [di], ax
add si, 2
add di, 2
loop s
mov ax, 4c00h
int 21h
codesg ends
end start
汇编指令 | 语法描述 |
---|---|
[idata] | 用一个常量表示地址,直接定位一个内存单元 |
[bx(或 si、di)] | 用一个变量来表示内存地址,间接定位一个内存单元 |
[bx(或 si、di)+idata] | 用一个变量和常量表示地址,在一个起始地址的基础上用变量间接定位一个内存单元 |
[bx+si(或 di)] | 用两个变量表示地址 |
[bx+si(或 di)+idata] | 用两个变量和一个常量表示地址 |
使用栈暂存数据
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, stacksg
mov ss, ax
mov sp, 16
mov ax, datasg
mov ds, ax
mov bx, 0
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
add bx, 16
pop cx
loop s0
mov ax, 4c00h
int 21h
codesg ends
end start