《汇编语言》——第七章:更灵活的定位内存地址的方法及汇编下的多重循环

好久不见. 提交于 2020-02-23 04:46:29

《汇编语言》——第七章:更灵活的定位内存地址的方法

1.and和or指令

  • and指令:将操作对象的相应位设为0,其他位不变
  • or指令:将操作对象的相应位设为1,其他位不变

2.以字符形式给出的数据

  • 在汇编程序中,用’ '的方式指明数据是以字符的形式给出的,编译器将把它们转化为相对应的ASCII码
  • db 'unIX'相当于db 75H,6EH,49H,58H
  • 小写字母的ASCII码值比大写字母的ASCII码值大20H,故,“a"的ASCII码值减去20H,就可以得到"A”
  • 一个字母,不管它原来是大写还是小写,将它的位置的第6位置0,它就必将变为大写字母,将它的第6位置1,它就必将变为小写字母
  • 代码实现大小写改变
    assume cs:cscode,ds:datasg
    
    datasg segment
    db 'BaSiC'
    db 'iNfOrMaTiOn'
    datasg ends
    
    cscode segment
    start:  mov ax,datasg
            mov ds,ax			;设置ds指向datasg段
    
            mov bx,0			;设置(bx)=0,ds:bx指向"BaSiC"的第一个字母
    
            mov cx,5			;设置循环次数5,因为"BaSiC"的有5个字母
        s:	mov al,[bx]			;将ASCII码从ds:bx所指向的单元中取出
            and al,11011111b	        ;将al中的ASCII码的第6位置为0,变为大写字母
            mov [bx],al			;将转变后的ASCII码写回原单元
            inc bx 				;(bx)加1,ds:bx指向下一个字母
            loop s
    
            mov ax,4c00h
            int 21h
    cscode ends
    end start					;指明程序的入口在start处
    

3.不同的寻址方法的灵活应用

  • SI和DI是8086CPU中和bx功能相近的寄存器,但是SI和DI不能够分成两个8位寄存器来使用
  • [idata]用一个常量来表示地址,可用于直接定位一个内存单元
  • [bx]用一个变量来表示内存地址,可用于间接定位一个内存单元
  • [bx+idata]用一个变量和常量表示地址,可在一个起始地址的基础上用变量间接定位一个内存单元
  • [bx+si]用两个变量表示地址
  • [bx+si+idata]用两个变量和一个常量表示地址
  • 例,将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 ends
    
    codesg segment
    start:	
    codesg ends
    end start
    
  • 思考后,要亲手打一遍
    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 ends
    
    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
    

4.多重循环

  • 进行二重循环时,使用一个循环计数器,造成在进行内层的时候覆盖了外层循环的循环计数值
  • 多用一个计数器又不可能,因为loop指令默认cx为循环计数器
  • 解决方法:在每次开始内层循环的时候,将外层循环的cx中的数值保存起来,在执行外层循环的loop指令前,再恢复外层循环的cx数值
  • 但是8086的寄存器是有限的,其他寄存器被占用导致没有寄存器可以保存外层循环的数值怎么办?=>即,程序中经常需要进行数据的暂存,我们该如何做将更为合理?

    暂存数据,可以使用栈的操作(栈是真的顶!!!)

  • 例,将datasg段中每个单词改为大写字母
    assume cs:codesg,ds:datasg
    
    datasg segment
      
    datasg ends
    
    codesg segment
    start:
    codesg ends
    end start
    
  • 思考后,要亲手打一遍
    assume cs:codesg,ds:datasg,ss:stacksg
    
    datasg segment
      db 'ibm             '
      db 'dec             '
      db 'dos             '
      db 'vax             '
    datasg ends
    
    stacksg segment		       ;定义一个栈段,容量为16个字节
      dw 0,0,0,0,0,0,0,0 
    stacksg ends
    
    codesg segment
    start:	mov ax,datasg
        mov ds,ax
        mov ax,stacksg
        mov ss,ax
        mov sp,16
        
        mov bx,0h
        mov cx,4
    s:  push cx			;将外层循环的cx值压栈
        mov cx,3
        mov si,0		        ;cx设置为内层循环的次数
    
    s0: mov al,[bx+si]
        and al,11011111b
        mov [bx+si],al
        inc si
        loop s0
    
        add bx,10h
        pop cx 			;从栈顶弹出原cx的值,恢复cx
        loop s 			;外层循环的loop指令将cx中的计数值减一
    
        mov ax,4c00h
        int 21h
    codesg ends
    end start
    
    要实践,把书上的代码自己打一遍、debug一遍
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!