灵活定位内存地址

 and 和 or 指令

1、and 指令:逻辑与指令,按位进行与运算。
mov al , 01100011B
and al ,  00111011B      ; 结果00100011B
可以用来将操作对象的相应位设为 0 ,其他位不变。
2、or 指令:逻辑或指令,按位进行或运算。
mov al , 01100011B
or al ,     00111011B     ; j结果01111011B
可以用来将操作对象的相应位设置为 1 ,其他位不变。




计算机中的 ASCII 码

编码规则,文本编辑过程就是按照ASCII码规则进行的编码和解码。当我们按下键盘的一个 a ,这个按键信息被送入计算机,计算机用ASCII码规则对其进行编码,将其转化为61H存储在内存指定空间;文本编辑软件取出内存中的61H,将其送到显卡的显存中;工作在文本模式下的显卡,用ASCII码规则解释显存中的内容,61H被当做字符“a”,显卡驱动显示器,将字符“a”的图像画在屏幕上。




以字符形式给出的数据

在汇编程序中,用‘...’的方式指明数据是以字符的形式给出的,编译器把它们转化为相应的 ascii 。
assume ds:data , cs:code
data segment
     db 'unIX'
     db 'foRK'
data ends
code segment
start:    mov al , 'a'
             mov bl , 'b'
             mov ax , 4c00h
             int 21h
code ends
end start
db 'unIX' 相当于“db 75h , 6eh , 49h , 58h”
db 'foRK' 相当于“db 66h , 6fh , 52h , 4bh”
mov al , 'a' 相当于 "mov al , 61h"

  // 这个程序运行第一条指令指向mov al 'a' ;数据肯定存放在这条指令的上面,就是 076A:0

;定义程序,把字符串的大写改小写,小写改大写
assume cs:codesg , ds:datasg
datasg segment
        db 'BaSic'
        db 'iNfOrMaTion'
datasg ends
codedg segment
start:   mov ax , datasg                  ;设置 ds 指向 datasg 段 ;这条指令执行的同时,系统就把数据段的空间分配好了
            mov ds , ax
            mov bx , 0                           ;设置(bx)=0,ds:bx指向 'BaSic' 的第一个字母
            mov cx , 5          
s:         mov al , [bx]                        ;取出 'B'  放到 al 中
           and al , 11011111B            ;转换,因为大写和小写字母只是二进制的第5位不一样;小写字母第5位为1,改成0就变成相应的大写
           mov [bx] , al                        ;转换完成,写回原单元。
           inc bx                                   ;偏移一位,指向下一个字母
           loop s
           mov bx , 5                            ;设置偏移,指向'iNfOrMaTiOn'的第一个字母
           mov cx , 11                          ;设置循环次数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
eg:mov ax , [bx+200]    ; 将一个内存单元的内容送入 ax , 这个内存单元的长度为2字节(字单元),存放一个字,偏移地址为 bx 中的数值加上 200,段地址在 ds 中。
mov ax , [200+bx]
mov ax , 200[bx]
mov ax , [bx].200  ;立即数不在最开头就要前面加一个.





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

改写上面那个程序字符大写改小写,小写改大写的程序
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
             mov al , [5+bx]
             or al , 00100000B
             mov [5+bx] , al                        ; 第一次5次循环直接可以同时操作两个串,如果两个字符串一样效率更高
             inc bx
             loop s
             mov cx , 6
             inc bx
s0:        mov al , [5+bx]                          ; 处理较长的字符串剩下的字符
             or al , 00100000B
             loop s0

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





SI 和 DI

SI 和 DI 是8086CPU中和 bx 功能相近的寄存器,SI 和 DI 不能够分成两个 8 位寄存器来使用
 SI:源变址寄存器;   DI:目的变址寄存器;
mov bx , 0
mov ax , [bx]
mov si , 0
mov ax , [si]
mov di
mov ax , [di]
*3组指令效果一样
;用 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 , 16
            mov cx , 8
s:          mov ax , [si]
            mov [di] , ax 
            add si , 2               ;si 和 di 不能分成两个8寄存器,所以一次拷贝会拷贝16位2个字节,每次循环+2
            add di , 2
            loop s
            mov ax , 4c00h
            int 21h
codesg ends
end start
tips:start后面紧更着冒号
    





[bx+si] 和 [bx+di]




[bx+si+idata] 和 [bx+di+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

;将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
s0:           mov dx , cx      ;暂存外层循环cx的值
                mov si , 0 
                mov cx , 3       ;cx设置为内层循环的次数
s:              mov al , [bx+si]
                and al , 11011111B
                mov [bx+si] , al
                inc si 
                loop s
                add bx , 16
                mov cx , dx     ;恢复外层循环cx的值
                loop s0
codesg ends
end start
; 程序每次修改一行的字符,然后转到下一行,所以用到两个循环,不得不暂存cx的值,但是cpu的寄存器是有限的;如果寄存器不够用,最好的办法是用一个指定的内存地址来暂存数据,ds:[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     ;栈段暂存外层循环cx的值
                mov si , 0
                mov cx , 3     ;cx设置为内层循环的次数
s:              mov al , [bx+si]
                and al , 11011111B
                mov [bx+si] , al
                inc si
                loop s
                add bx , 16
                pop cx        ;恢复外层循环cx的值
                loop s0
codesg ends
end start






原文地址:https://www.cnblogs.com/meihao1203/p/7546053.html