Skip to content

更灵活的定位内存地址的方法

and 与 or 指令

and(逻辑与): 按位与,可以将某些位清零(与 0 相与):

asm
mov al, 01100011b
and al, 00111011b   ; al = 00100011b(两者都是 1 的位保留)

or(逻辑或): 按位或,可以将某些位置 1(与 1 相或):

asm
mov al, 01100011b
or  al, 00111011b   ; al = 01111011b(任意一方是 1 的位置 1)

ASCII 码与字符处理

大写字母 A~Z 的 ASCII 码范围:41H~5AH(二进制第 5 位为 0) 小写字母 a~z 的 ASCII 码范围:61H~7AH(二进制第 5 位为 1)

大小写转换技巧:

asm
; 将 al 中的字母转换为大写(清除第 5 位)
and al, 11011111b

; 将 al 中的字母转换为小写(置 1 第 5 位)
or  al, 00100000b

实例: 将第一个字符串转大写,第二个转小写

asm
assume cs:codesg, ds:datasg

datasg segment
    db 'BaSiC'           ; 5 字节,偏移 0~4
    db 'iNfOrMaTiOn'     ; 11 字节,偏移 5~15
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

asm
mov ax, [bx+200]    ; 等同写法:
mov ax, [200+bx]
mov ax, 200[bx]
mov ax, [bx].200

利用 [bx+idata] 同时处理两个数组(C 风格对比):

c
// C 语言
char a[5] = "BaSiC";
char b[5] = "MinIX";
for (int i = 0; i < 5; i++) {
    a[i] = a[i] & 0xDF;   // 转大写
    b[i] = b[i] | 0x20;   // 转小写
}
asm
; 汇编等价:a[i] → 0[bx],b[i] → 5[bx]
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]        ; a[i]
    and al, 11011111b
    mov [bx], al

    mov al, 5[bx]       ; b[i](偏移 5 个字节)
    or  al, 00100000b
    mov 5[bx], al

    inc bx
    loop s

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

SI 和 DI 寄存器

SI(Source Index)和 DI(Destination Index)与 BX 功能相近,但不能拆分为 8 位寄存器使用。

常用于字符串操作(SI 指向源,DI 指向目标):

asm
; 将 'welcome to masm!' 复制到其后的 16 字节空间
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 cx, 8           ; 一次复制 2 字节,共 8 次 = 16 字节

s:  mov ax, 0[si]       ; 读取源字符串中的字
    mov 16[si], ax      ; 写入目标区域
    add si, 2
    loop s

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

[bx+si] 和 [bx+di] 寻址

8086 CPU 中,[...] 内可用于寻址的寄存器只有 4 个:bx, si, di, bp

合法的组合形式:

asm
mov ax, [bx]
mov ax, [bx+si]
mov ax, [bx+si+idata]
mov ax, [bx+di]
mov ax, [bx+di+idata]
mov ax, [bp]
mov ax, [bp+si]
mov ax, [bp+si+idata]
mov ax, [bp+di]
mov ax, [bp+di+idata]

合法的配对:bx+si, bx+di, bp+si, bp+di不能 bx+bpsi+di

bp 的默认段寄存器是 SS(不是 DS):

asm
mov ax, [bp]            ; 等同于 (ax) = ((ss)*16 + (bp))
mov ax, ds:[bp]         ; 显式指定 ds,则用 ds