【不求甚解】《汇编语言》第 7 章:更灵活的定位内存地址的方法


前言

参考书籍:
王爽。汇编语言。北京:清华大学出版社, 2013:138-160

本人菜狗一枚,不敢咬文嚼字,只能站在巨人的肩膀上窥探一下未曾了解的世界。


and 和 or 指令

  1. and 指令:逻辑指令,按位进行与运算

    mov al, 0000 0101B
    and al, 0000 0110B  
    ;  ax = 0000 0000B
    

    通过该指令可将操作对象的相应位设为 0,其余位不变。

  2. or 指令:逻辑指令,按位进行或运算

    mov al, 0000 0101B
    or al,  0000 0110B
    ; ax =  0000 0111B
    

    通过该指令可将操作对象的相应位设为 1,其余位不变。

操作对象指令数值结果
1and11
1and00
0and10
0and00
1or11
1or01
0or11
0or00

以字符形式给出的数据

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

大小写转换的问题

大写十六进制二进制  小写十六进制二进制
A4101000001a6101100001
B4201000010b6201100010
C4301000011c6301100011
D4401000100d6401100100
E4501000101e6501100101
F4601000110f6601100110

就 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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值