1. 程式人生 > >匯編語言——更靈活的定位內存地址的方法

匯編語言——更靈活的定位內存地址的方法

獲取 寄存器 ima nbsp assume 它的 偏移地址 pre tro

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

匯編語言——更靈活的定位內存地址的方法