更灵活的定位内存地址的方法---汇编学习笔记

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

前面,我们用[0]、[bx]的方法,在访问内存的指令中,定位内存单元的地址。本章将用更灵活的方式来定位内存地址。


7.1 and和or指令

(1)and指令:逻辑与指令,按位进行与运算。例如:

mov al,01100011B
and al,00111011B
;执行后:al = 00100011B

(2)or指令:逻辑或指令,按位进行或运算。例如:

mov al,01100011B
or al,00111011B
;执行后:al = 01111011B

7.2 关于ASCII码


7.3 以字符形式给出的数据

‘……’的方式指明数据是以字符的形式给出,编译器将它们转化为相应的ASCII码。如下:

assume cs:code,ds:data
data segment
    db 'unIX'   ;相当于 db 75H,6EH,49H,58H
    db 'foRK'   ;同理,下面的也是
data ends

code segment
start:  mov al,'a'
        mov bl,'b'
        mov ax,4c00h
        int 21h
code ends
end start

debug运行查看是否:
这里写图片描述
先用r命令分析一下data段的地址,因“ds=075A”,所以程序从076AH段开始,data段又是程序中的第一个段,它就在程序的起始处,所以它的段地址为0B3DH


7.4 大小写转换的问题

考虑这样一个问题,在codesg中填写代码,将datasg中的第一个字符串转化为大写,第二个字符串转化为小写。

assume cs:codesg,ds:datasg
datasg segment
    db 'BaSic'
    db 'iNfOrMaTiOn'
datasg ends
codesg segment
    start:
codesg ends
ends start

主要问题是怎么判断一个字母是大写还是小写?不过我们好像没有学过如何判断一个字母大小写的指令。所以该怎么办呢?

我们观察发现,ASCII码的二进制形式有一个规律!如下:
这里写图片描述
因此,我们可以用刚刚学过的and和or来做这个实验!这里指出方法:
变成大写:只要and al,11011111B
变成小写:只要or al,00100000B


7.5 [bx+idata]

指令mov ax,[bx+200]中的[bx+200]数学化的描述:(ax) = ((ds)*16+(bx)+200)。

问题 7.1
用Debug查看内存,结果如下:
2000:1000 BE 00 06 00 00 00 …
写出下面的程序执行后,ax、bx、cx中的内容。

mov ax,2000H    ;ax=2000h
mov ds,ax       ;ds=2000h
mov bx,1000H    ;bx=1000h
mov ax,[bx]     ;ax=00BEh
mov cx,[bx+1]   ;cx=0600h
add cx,[bx+2]   ;cx=0606h

7.6 用[bx+idata]的方式进行数组的处理

我们经常用的一个策略,这里直接略过吧!


7.7 SI和DI

si和di是8086CPU中和bx功能相近的寄存器,si和di不能够分成两个8位寄存器来使用

下面3组实现了相同的功能:

;第一组
mov bx,0
mov ax,[bx]
mov ax,[bx+123]

;第二组
mov si,0
mov ax,[si]
mov ax,[si+123]

;第三组
mov di,0
mov ax,[di]
mov ax,[di+123]

问题 7.2
用si和di实现字符串’welcome to masm!’复制到它后面的数据区中。

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,10h

        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

问题 7.3
用更少的代码,实现问题7.2的程序
答案如下:

codesg segment
    start:  
        mov ax,datasg
        mov ds,ax
        mov si,0

        mov cx,8

    s:  
        mov ax,[si]
        mov [si+16],ax
        add si,2
        loop s

        mov ax,4c00h
        int 21h

codesg ends
end start

7.8 [bx+si]和[bx+di]

指令mov ax,[bx+si]中的[bx+si]数学化的描述:(ax) = ((ds)*16+(bx)+(si))。

问题 7.4
用Debug查看内存,结果如下:
2000:1000 BE 00 06 00 00 00 …
写出下面的程序执行后,ax、bx、cx中的内容。

mov ax,2000h    ;ax=2000h
mov ds,ax       ;ds=2000h
mov bx,1000h    ;bx=1000h
mov si,0        ;si=0h
mov ax,[bx+si]  ;ax=00beh
inc si          ;si=1h
mov cx,[bx+si]  ;cx=0600h
inc si          ;si=2h
mov di,si       ;di=2h
add cx,[bx+di]  ;cx=0606h

7.9 [bx+si+idata]和[bx+di+idata]

指令mov ax,[bx+si+idata]中的[bx+si+idata]数学化的描述:(ax) = ((ds)*16+(bx)+(si)+(idata))。

问题 7.5
用Debug查看内存,结果如下:
2000:1000 BE 00 06 00 6A 22 …
写出下面的程序执行后,ax、bx、cx中的内容。

mov ax,2000h        ;ax=2000h
mov ds,ax           ;ds=2000h
mov bx,1000h        ;bx=1000h
mov si,0            ;si=0h
mov ax,[bx+2+si]    ;ax=0006h
inc si              ;si=1h
mov cx,[bx+2+si]    ;cx=6a00h
inc si              ;si=2h
mov di,si           ;di=2h
mov bx,[bx+2+di]    ;bx=226ah

7.10 不同的寻址方式的灵活应用

(1)[idata]用一个变量来表示地址,可用于直接定位一个内存单元。
(2)[bx]用一个变量来表示内存地址,可用于间接定位一个内存单元。
(3)[bx+idata]用一个变量和常量表示地址,可在一个起始地址的基础上用变量间接定位一个内存单元。
(4)[bx+si]用两个变量表示地址。
(5)[bx+si+idata]用两个变量和一个常量表示地址。

问题 7.6
编程,将datasg段中每个单词的头一个字母改为大写字母。

assume cs:codesg,ds:datasg
datasg segment
    db '1. file         '
    db '2. edit         '
    db '3. search       '
    db '4. view         '
    db '5. options      '
    db '6. help         '
datasg segment

codesg segment
    start:
        ;答案如下:
        mov ax,datasg
        mov ds,ax
        mov bx,0
        mov cx,6
    s:
        mov al,[bx+3]
        and al,11011111B
        mov [bx+3],al
        add bx,10h
        loop s

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

问题 7.7
编程,将datasg段中每个单词改为大写字母。

assume cs:codesg,ds:datasg
datasg segment
    db 'ibm             '
    db 'dec             '
    db 'dos             '
    db 'vax             '
datasg ends

codesg segment
    start:
        ;答案如下:
        mov ax,datasg
        mov ds,ax
        mov bx,0
        mov cx,4
    s:
        mov dx,cx
        mov si,0
        mov cx,3
    s0:
        mov al,[bx+si]
        and al,11011111b
        mov [bx+si],al
        inc si
        loop s0

        add bx,10h
        mov cx,dx
        loop s

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

其实,我们这里存cx应该需要用栈来存储。这是我们常用的方法,也是递归的本质

如下:

assume cs:codesg,ss:stacksg,ds:datasg
;增加了栈空间
stacksg segment
    dw 0,0,0,0,0,0,0,0
stacksg ends

datasg segment
    db 'ibm             '
    db 'dec             '
    db 'dos             '
    db 'vax             '
datasg ends

codesg segment
    start:
        ;答案如下:
        mov ax,datasg
        mov ds,ax
        mov bx,0
        mov cx,4
    s:
        push cx    ;这里改变了
        mov si,0
        mov cx,3
    s0:
        mov al,[bx+si]
        and al,11011111b
        mov [bx+si],al
        inc si
        loop s0

        add bx,10h
        pop cx    ;这里也改变了
        loop s

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

总结

这一章,我们主要学习了寻址方式:

  1. 寻址方式[bx(或 si、di)+idata]、[bx+si(或 di)]、[bx+si(或 di)+idata]的意义和应用。
  2. 二重循环问题的处理
  3. 栈的应用
  4. 大小写转化的方法
  5. and、or指令

实验6 实践课程中的程序

(1)将课程中所有讲解过的程序上机调试,用Debug跟踪其执行过程,并在过程中进一步理解所讲内容。
(2)编程,完成问题7.9中的程序。将下面datasg段的每个单词的前4个字母改为大写!

assume cs:codesg,ss:stacksg,ds:datasg

stacksg segment
    dw 0,0,0,0,0,0,0,0
stacksg ends

datasg segment
    db '1. display      '
    db '2. brows        '
    db '3. replace      '
    db '4. modify       '
datasg ends

codesg segment
    start:
        mov ax,datasg
        mov ds,ax
        mov bx,0
        mov cx,4

    s:  
        push cx
        mov si,0
        mov cx,4

    s0:
        mov al,[bx+si+3]
        and al,11011111b
        mov [bx+si+3],al
        inc si
        loop s0

        add bx,16
        pop cx
        loop s

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

实验结果如下:
这里写图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值