• 汇编语言——更灵活的定位内存地址的方法


    and和or指令

    1、and指令

    将2进制中的1当做真,2进制中的0当做假

    则:只有2个事件都为真的时候才为真,即1&&1==>1,1&&0==>0,0&&0==>0;

    用处:假如想把一个数的第7位变成0,让它和01111111B执行与操作就好了

    1 mov al,10001101B    ; 8位数据
    2 
    3 add al,01111111B
    4 
    5 >> (al)=00001101B

    2、or指令

    只要2个事件中有1个是真即为真,即1||1==>1,1||0==>1,0||0==>0;

    用处:假如想把一个数的第7位变成1,让它和10000000B执行或操作就好了

    mov al,01101101B    ; 8位数据
    
    or al,10000000B
    
    >> (al)=11101101B

    ASCII码

    大小写转换

    由上图可以得知大写字母的ASCII码比小写字母的ASCII码小32(20H),也就是说大写字母和小写只有第5位不同(大写:0,小写:1)

    大写     二进制             小写       二进制
     A         01000001          a         01100001
     B         01000010          b         01100010
     C         01000011          c         01100011
     D         01000100          d        01100100

    示例:将BaSiC全部变成大写,将iNfOrMaTiOn全部变成小写。

     1 assume cs:codesg,ds:datasg
     2 datasg segment
     3     db 'BaSiC'            ; 0~4内存单元
     4     db 'iNfOrMaTiOn'    ; 5~15内存单元
     5 datasg ends
     6 
     7 codesg segment
     8  start: mov ax,datasg
     9         mov ds,ax
    10         mov bx,0
    11         mov cx,5        ; 循环5次
    12         
    13         ; 将BaSiC全部变成大写
    14       s:mov al,[bx]          ; 获取相应内存单元的值,赋给al低位寄存器
    15         add al,11011111B; 将第5位变成0
    16         mov [bx],al        ; 将修改后的放回之前的内存单元
    17         inc bx            ; bx自增1
    18         loop s
    19         
    20         mov bx,5
    21         mov cx,11
    22         ; 将iNfOrMaTiOn全部变成小写
    23      s0:mov al,[bx]
    24         or al,00100000B ; 将第5位变成0
    25         mov [bx],al
    26         inc bx
    27         loop s0
    28   
    29 codesg ends
    30 end start

    [bx+idata]

    我们可以用[bx]的方式来指明一个内存单元, 我们还可以用一种更为灵活的方式来指明内存单元:
    [bx+idata]表示一个内存单元,它的偏移地址为(bx)+idata(bx中的数值加上idata)。

    示例:使用[bx+idata],将BaSiC全变小写,将MinIX全变大写

     1 assume cs:codesg,ds:datasg
     2 datasg segment
     3     db 'BaSiC'        ; 内存单元0-4
     4     db 'MinIX'        ; 内存单元5-9
     5 datasg ends
     6 
     7 codesg segment
     8  start: mov ax,datasg
     9         mov ds,ax
    10         
    11         mov bx,0
    12         mov cx,5
    13         
    14       s:mov al,[bx]
    15         or al,00100000B        ; 或操作,全变成小写
    16         mov [bx],al
    17         
    18         mov bl,[bx+5]
    19         and al,11011111B    ; 与操作,全变成大写
    20         mov [bx+5],al
    21         inc bx
    22         loop s
    23         
    24         mov ax,4c00H
    25         int 21H
    26  
    27 codesg ends
    28 end start

    SI和DI寄存器

    si和di寄存器和ds寄存器的作用一样,都是用来表示内存的偏移地址的。只是SI和DI不能够分成两个8 位寄存器来使用。

    我们还可以这样使用它们:[bx+si],[bx+di]和[bx+si+idata],[bx+di+idata],其实和[dx+idata]一样

    示例:*****

    将datasg段中每个单词改为大写字母

    我们很容易就会想到以下代码,因为在第2层循环中修改了cx。等它们跳出第二层循环时cx=0,第一层循环会执行cx=cx-1 ==>-1(FFFF),从而进入死循环

     1 assume cs:codesg,ds:datasg
     2 datasg segment
     3    db 'ibm            '        ; 16个字节 0-15
     4    db 'dec            '        ; 16-31
     5    db 'dos            '        ; 32-47
     6    db 'vax            '        ; 48-63
     7 datasg ends
     8 
     9 codesg segment
    10  start: ; 因为要将每行的每个单词改为大写,所以我们需要写两层循环
    11         mov ax,datasg
    12         mov ds,ax
    13         mov bx
    14         mov cx,4
    15       s:mov cx,3
    16         mov so,0    ; 这个要写在外面
    17      s0:   
    18         mov al,[bx+si]  
    19         add al,11011111B
    20         mov [bx+si],al
    21         inc si        ; 如果是将bx+1的话,就会1,2,3,13,14,15,...这样,所以我们要用si/di寄存器
    22         loop s0
    23         
    24         add bx,16
    25         loop s
    26         
    27         mov ax,4c00H
    28         int 21H
    29         
    30 codesg ends
    31 end start

    我们可以采用把cx的值放进其他寄存器中,但寄存器是有限的,当程序过大就不够用了

     1 assume cs:codesg,ds:datasg
     2 datasg segment
     3    db 'ibm            '        ; 16个字节 0-15
     4    db 'dec            '        ; 16-31
     5    db 'dos            '        ; 32-47
     6    db 'vax            '        ; 48-63
     7 datasg ends
     8 
     9 codesg segment
    10  start: 
    11         mov ax,datasg
    12         mov ds,ax
    13         mov bx
    14         mov cx,4
    15       s:mov cx,3
    16         mov dx,cx    ;;;;;; 用其他寄存器保存一下
    17       
    18      s0:mov si,0    
    19         mov al,[bx+si]  
    20         add al,11011111B
    21         mov [bx+si],al
    22         inc si        
    23         loop s0
    24         
    25         add bx,16
    26         mov cx,dx    ;;;;; 将cx取出
    27         loop s
    28         
    29         mov ax,4c00H
    30         int 21H
    31         
    32 codesg ends
    33 end start
    View Code

    然后我们可以把他放进内存中,内存是可以随便用的啊,但当循环多的时候,你需要把所以内存位置都记住。这很不方便

     1 assume cs:codesg,ds:datasg
     2 datasg segment
     3    db 'ibm            '        ; 16个字节 0-15
     4    db 'dec            '        ; 16-31
     5    db 'dos            '        ; 32-47
     6    db 'vax            '        ; 48-63
     7    dw  0        ;;;;; 定义一个字来保存cx的值(64)
     8 datasg ends
     9 
    10 codesg segment
    11  start: 
    12         mov ax,datasg
    13         mov ds,ax
    14         mov bx,0
    15         mov cx,4
    16       s:mov cx,3
    17         mov [64],cx    ;;;;;; 放进字单元中保存一下
    18         mov si,0    
    19      s0:    
    20         mov al,[bx+si]  
    21         add al,11011111B
    22         mov [bx+si],al
    23         inc si        
    24         loop s0
    25         
    26         add bx,16
    27         mov cx,[64]    ;;;;; 将cx取出
    28         loop s
    29         
    30         mov ax,4c00H
    31         int 21H
    32         
    33 codesg ends
    34 end start
    View Code

    所以我们要使用栈的方式来进行两层循环的嵌套

    这样做的好处是:多层循环嵌套的话,每一层往里面push一个值,等它出来的时候pop的值就是那个,我们只需要管理一个栈就好了,不用管其他的。

     1 assume cs:codesg,ds:datasg,ss:stacksg
     2 datasg segment
     3    db 'ibm            '        ; 16个字节 0-15
     4    db 'dec            '        ; 16-31
     5    db 'dos            '        ; 32-47
     6    db 'vax            '        ; 48-63
     7 datasg ends
     8 
     9 stacksg segment
    10     dw 0,0,0,0,0,0,0,0        ;;;;; 定义一个栈段
    11 
    12 codesg segment
    13  start: 
    14         mov ax,datasg
    15         mov ds,ax
    16         mov ax,stacksg        ;;;;; 保存栈段的位置
    17         mov ss,ax            ;;;;; 赋值给ss
    18         mov sp,16            ;;;;; 指向栈顶
    19         mov bx,0
    20         mov cx,4
    21       s:mov cx,3
    22         push cx    ;;;;;; 入栈
    23         mov si,0    
    24      s0:    
    25         mov al,[bx+si]  
    26         add al,11011111B
    27         mov [bx+si],al
    28         inc si        
    29         loop s0
    30         
    31         add bx,16
    32         pop cx     ;;;;; 出栈
    33         loop s
    34         
    35         mov ax,4c00H
    36         int 21H
    37         
    38 codesg ends
    39 end start
  • 相关阅读:
    Microsoft Visual C++ Compiler for Python
    ArcGIS Server的Tile的松散型存储(Exploded)
    git下载指定版本的代码
    C#+SharpMap的相关代码
    C#+MapServer相关代码
    WebGIS点要素渲染性能测试
    Docker的4种网络模式
    AngularJS中的指令全面解析(转载)
    风云2号云图Mosaic Dataset处理
    查找错误的等值线中的高程点
  • 原文地址:https://www.cnblogs.com/x54256/p/8094131.html
Copyright © 2020-2023  润新知