汇编网首页登录博客注册
xcc的学习博客
博客首页博客互动【做检测题】论坛求助

我的博客

个人首页 |  我的文章 |  我的相册 |  我的好友 |  最新访客 |  文章收藏 |  论坛提问 |  友情链接 |  给我留言  
图片载入中
学习动态
最新评论
文章收藏

[2013-12-08 21:12] 第七章 (答案属于个人解答,如有问题请留言指教交流,谢谢!O(∩_∩)O~)

更灵活的定位内存地址的方法
        之前:[idata]、[bx]
7.1 and  和 or 指令。
        (1)and 指令:逻辑与指令,按位进行 与 运算。
                通过该指令可将操作对象的相应位设为0,其他位不变。(异位为0)
                将al的第6位设为0的指令是:and al,10111111B
                将al的第7位设为0的指令是:and al,01111111B
        (2) or 指令  :逻辑或指令,按位进行 或 运算。
                通过该指令可将操作对象的相应位设为1,其他位不变。(异位为1)
                将al的第6位设为0的指令是:and al,01000000B
                将al的第7位设为0的指令是:and al,10000000B
7.2关于ASCII码
        世界上有很多编码方案,有一种方案叫做ASCII编码,是计算机系统中通常被采用的。(一套规则)
        显示a:将a的ASCII的编码放入显存中,再通过ASCII码的规则将a画到显示器中。
7.3以字符形式给出的数据
        我们可以再汇编程序中,用"....."的方式指明数据是以字符的形式给出的,编译器将把他们转化为相应的ASCII码。
        如:
        assume cs:code,ds:data
        data segment
                db        'nuIX'
                db        'foRK'
        data ends
        code segment
                start:        mov al,'a'
                                mov bl,'b'
                                mov ax,4c00h
                                int 21h
        code ends
        end start
        "db 'nuIX'" 相当于 "db 75H,6EH,49H,58H"。
        "db 'foRK'" 相当于"db 66H、6FH、52H、4BH"。
        "mov al,'a'"相当于"mov al,61H"。
        "mov bl,'b'"相当于"mov al,62H"。
7.4大小写转换的问题。
        如果一个问题的解决方案,使我们陷入一种矛盾之中。那么,很可能是我们考虑问题的出发点有了问题,或是说,我们起初运用的规律并不合适。
        规律一:大写字母+20H=小写字母,小写字母-20H=大写字母。这使我们陷入这样的一个矛盾中:必须判断是大写字母还是小写字母,才能决定进行何种处理,而我们现在又没有可以使用的用于判断的指令。
        规律二:就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 ax,11
                        s0:mov al,[bx]
                           or al,00100000B
                           mov [bx],al
                           inc bx
                           loop s0

                           mov ax,4c00h
                           int 21h
                codeseg ends
                end start.
7.5[bx+idata]
        [bx+idata]表示一个内存单元,它的便宜地址为(bx)+idata(bx中的数值加上idata)
        用Debug查看查看内存,结果如下:
                2000:1000 BE 00 06 00 00 00 ......
        写出下面的程序执行后后,ax、bx、cx中的内容。
        mov ax,2000H
        mov ds,ax
        mov bx,1000H
        mov ax,[bx]
        mov cx,[bx+1]
        mov cx,[bx+2]
        我的解答:ax=00BE、bx=1000H、cx=0606
7.6 用[bx + idata]的方式进行数组的处理
        在codesg中填写代码,将dataseg中定义的第一个字符串转化为大写,第二个字符串转化为小写。
                assume cs:codeseg,da:detasg
                        datasg segment
                                db 'BaSic'
                                db 'MinInx'
                        datasg ends
                codesg segment
                start:
                codesg ends
                end start
        改进的程序:
                mov ax,da
                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,datasg
                mov ds,ax
                mov bx,0

                mov cx,5
        s:        mov al,0[bx]
                and al,11011111b
                mov 0[bx],al
                mov al,5[bx]
                or al,00100000b
                mov 5[bx],al
                inc bx
                loop s
        如果用C来写:
                char a[5]="BaSic";
                char b[5]="MinInx";

                main()
                {
                        int i;
                        i =0;
                        do
                        {
                                a[i] =a[i] &0xDF;
                                b[i] =b[i] | 0x20;
                                i++;
                        }
                        while(i<5);
                }
        比较相似之处:尤其是定位字符串中字符的方式。
                C:a[i],b[i]'
                汇编:0[bx],5[bx]
        通过比较,我们可以发现,[bx+idata]的方式为高级语实现数组提供了便利机制。
7.7SI和DI
        SI和DI是8086CPU中和bx功能相近的寄存器,SI和DI不能够分成两个8位寄存器来使用。
        问题7.2:用SI和DI实现将字符串‘welcome to masm!’复制到它后面的数据区中。
                assume c: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
                更简洁:
                分析:我们可以利用[bx(si或di)+idata]的方式,来使程序变得简洁。如下:
                codesg segment
                        start:        mov ax,datasg
                                        mov ds,ax
                                        mov si,0
                                        mov cs,8

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

                                        mov ax,4c00h
                                        int 21h
                        codesg        ends
                        end start
7.8[bx+si]和[bx+di]
        更灵活的指明偏移地址:[bx+si]和[bx+di]
        [bx+si]和[bx+di]的含义相似,指令mov ax,[bx+si]
        数学化得描述:(ax)=((ds)*16+(bx)+(si))
        也可以写成如下格式:mov        ax,[bx][si]
        问题:
                用Debug 查看内存,结果如下:
                2000:1000 BE 00 06 00 00 00 .......
                写出下面的程序,执行后、bx、cx中的内容。
                mov ax,2000h
                mov ds,ax
                mov bx,1000h
                mov si,0
                mov ax,[bx+si]
                inc si
                mov cx,[bx+si]
                inc si
                mov di,si
                add cx,[bx+di]
                解答后:ax=00BEh        bx=1000h        cx=0606h
7.9[bx+si+idata]和[bx+di+idata]
        他两含义相似。
        指令mov ax,[bx+si+idata]
        数学描述:(ax)=((ds)*16+(bx)+(si)+idata)
        也可以写成如下格式:
                mov ax,[bx+200+si]
                mov ax,[200+bx+si]
                mov ax,200[bx][si]
                mov ax,[bx].200[si]
                mov ax,[bx][si].200
        问题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=0
                mov ax,[bx+2+si]                 ax=0006h
                inc si                                si=1
                mov cx,[bx+2+si]                cx=ds:1000+2+1=6A00h
                inc si                                si=2
                mov di,si                        di=2
                mov bx,[bx+2+di]        bx=ds:1000+2+2=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       '
                datasg ends
                codesg segment
                        start:
                codesg        ends
                end start
        解答:
                mov ax,datasg
                mov ds,ax
                mov bx,0

                mov cx,6
        s:        mov al,[bx+3]                ;只是在寻址的时候加3.不是永久加3
                and al,11011111b
                mov [bx+3],al
                add bx,16
                loop s
        问题7.7
         编程,将datasg段中每个单词改为大写字母。
                assume cs:codesg,ds:datasg
                datasg segment
                        db:        'ibm             '
                        db:        'dec             '
                        db:        'dos                     '
                        db:        'vax             '
                datasg ends

                codesg segment
                start:
                codesg ends
        解答:
                start:mov ax,datasg
                        mov bx,0
                        mov cx,4

                S0:        mov dx,cx                ;将外层循环的cx值保存在dx中
                        mov di,0
                        mov cx,3                ;cx设置为内层循环的次数
                s:        mov al,[bx+di]
                        and al,11011111b
                        mov [bx+di],al
                        inc di
                        loop s

                        add bx,16
                        mov cx,dx
                        loop s0
                
                        mov ax,4c00h        ;用dx中存放的外层循环的计数器恢复cx
                        int 21h
        解答:(如果寄存器的个数不够怎么办?)
                assume cs:codesg,ds:datasg
                datasg segment
                        db:        'ibm             '
                        db:        'dec             '
                        db:        'dos                     '
                        db:        'vax             '
                        dw        0                                        ;定义一个字,用来暂存cx
                datasg ends

                codesg segment
                start:        mov ax,datasg
                                mov ds,ax
                                mov bx,0
                                mov cx,4
                        
                        s0:        mov ds:[40H],cx                ;将外层循环的cx值保存在datasg:40h单元中
                                mov si,0
                                mov cx,3
                        s:        mov al,ds:[bx+si]                
                                and al,11011111b
                                mov ds:[bx+si],al
                                inc si
                                loop s
                                
                                add bx,16
                                mov cx,ds:[40H]                ;用datasg:40h单元中的值恢复cx
                                loop s0                                ;外层循环的loop指令将cx中的计数值减1.
                                
                                mov ax,4c00h
                                int 21h
                codesg ends
        说明:上面的程序中,用内存单元来保存数据,可是上面的做法却有些麻烦,因为如果需要保存多个数据的时候,你必须要记住数据放到了那个单元中,这样程序容易混乱。
                一般来说,在需要暂存数据的时候,我们都应该使用盏。
        解答:(使用盏来暂存数据)
                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                                :定义一个段,用来做栈段,容量为16个字节
                stacksg segment
                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                                        ;将外层循环的cx值压栈
                                        mov si,0
                                        mov cx,3                                ;cx设置为内存循环的次数
                                
                                s:        mov al,ds:[bx+si]
                                        and al,11011111b
                                        mov ds:[bx+si],al
                                        inc si

                                        loop s

                                        add bx,16
                                        pop cx                                        ;从栈顶弹出cx的值,恢复cx

                                        loop S0                                        ;外层循环的loop指令将cx 中的计数值减1

                                        mov  ax,4c00h
                                        int 21h
                        codesg ends
                        end start
        问题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. display123456'
                        db        '2. brows12345678'
                        db        '3. replace123456'
                        db        '4. modify1234567'
                datasg        ends
                codesg        segment
                        start:
                codesg        ends

                end 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,4
        s:        mov al,ds:[bx+3+si]
                and al,11011111b
                mov ds:[bx+3+si],al
                inc si
                loop s

                add bx,16
                pop cx

                loop S0

                mov ax,4c00h
                int 21h
本章总结:寻址方式[bx(或si、di)+idata]、[bx+si(或 di)]、[bx+si(或di)+idata]的意义和应用;
                二重循环问题的处理。
                盏的应用;
                大小写转化的方法;
                and、or 指令。
寻址方式的适当应用,使我们可以以更合理的结构来看待所要处理的数据。
而为所要处理的看似杂乱的数据设计一种清晰的数据结构式程序设计的一个关键的问题。
评论次数(0)  |  浏览次数(484)  |  类型(反思) |  收藏此文  | 
 
 请输入验证码  (提示:点击验证码输入框,以获取验证码