1. 程式人生 > 實用技巧 >彙編之位操作指令

彙編之位操作指令

彙編之位操作指令


前言

位運算的特點是運算單元是位,一個位的變化不會對旁邊位產生影響。

邏輯運算指令

邏輯運算指令是位運算指令的子集,邏輯運算指的就是位運算指令中的與或非
ALU是算術邏輯單元,之前我們已經寫了彙編之算術運算指令這篇博文,已經研究了“運算”,現在我們來研究“邏輯”。所謂的硬體控制,其實也就是控制這幾個邏輯運算指令。

邏輯運算指令的通用格式是

AND/OR/XOR/TEST mem/reg,mem/reg/imm

(imm表示立即數定址)

邏輯運算指令都是按位進行操作的,其中
NOT指令執行後不影響任何標誌位,其他指令執行後,標誌位CF和OF一定是0;而SF、ZF和PF位則根據運算結果設定;AF位無定義。
換句話說,5個邏輯運算指令中只有NOT不影響標誌位

AND

在這裡插入圖片描述
常用於擷取或遮蔽若干位二進位制數
遮蔽——強行置0
如果要將一個數的第0,3,5位置零,只需要把這個數和1101 0110做AND即可

OR

在這裡插入圖片描述
可用於組合成某個字,或將某位置置1

XOR

在這裡插入圖片描述
同一個單元進行異或,相當於對單元清零

AND、OR和XOR

都是將結果回送給原運算元

TEST

在這裡插入圖片描述
TEST和AND的區別就是TEST的結果不回送,根據結果設定標誌位
想想

SUB-CMP
AND-TEST

是不是挺類似的?可以類比記憶

TEST常用於判斷運算元的某位或某幾位是“0”還是“1”
看一個例子

TEST AL,01H
TEST AL,80H

第一句,TEST AL,01H
可以用於判斷最低位是否為0
如果最低位是0,那麼結果全0,這時可以用零標誌位ZF判斷,如果ZF=1,說明結果等於0,也就是說AL的最低位是0
如果最低位是1,那麼結果是0000 0001,這是零標誌位ZF=0,我們看到零標誌位ZF=0,就能知道AL的最低位是1
根據最低位的0或1,可判斷這個數的奇偶性,所以TEST也有判斷奇偶的功能。

第二句,TEST AL,80H
可以用來判斷最高位是否為0

類似的,TEST AL,0110 0000可以用來判斷第5,6位是不是都是0
如果要你判斷1,2,3,5,7位是否都為1,那要怎麼做呢?
判斷是否都為0是很簡單的,直接TEST AL,1010 1110
如果運算結束後ZF=0,那麼就說明這些位置全都為0
但是如果要判斷都為1,那就比較麻煩,得一個一個判斷,先TEST AL,0000 0010,再……
還有一種方法是先取反,然後就變成了判斷這些位是否都為0,就比較簡單了。

總之,TEST是進行與運算,結果不回送,但根據結果設定標誌位。所以可以使用TEST指令,通過觀察標誌位,判斷操作位的某位或某幾位是0還是1。

NOT

在這裡插入圖片描述
在這裡插入圖片描述
NOT不同於與或異或,它是單運算元指令。
NOT就是求反,可以與NEG對比一下,他倆有點點像,但更多的是不同,NEG是求補指令,只針對負數。

邏輯運算指令應用例項

在這裡插入圖片描述
在這裡插入圖片描述

MOV AL,1011 1111
AND AL,1111 1100
結果是1011 1100
在這裡插入圖片描述
在這裡插入圖片描述
MOV AL,0100 0011
OR AL,0010 0000
結果是0110 0011
這兩句的作用是把AL的第五位置1
在這裡插入圖片描述
在這裡插入圖片描述
MOV AL,0100 0000
TEST AL,1010 1111
結果是全0,說明0,1,2,3,5,7位全部為0
(其實我覺得PPT第一條語句裡的040H沒必要寫成040H,寫成40H就行了,它又不是字母開頭的,不知道為什麼要在前面加0)
在這裡插入圖片描述
整個前三條語句是看DL中的第二位是否為1
但是其實想看DL中的第二位是否為1,直接把DL和0000 0100相TEST就行了,這裡的NOT對於判斷第二位沒什麼用,可能加在這是為了迷惑你吧。
TEST的下一步常常是跳轉指令,跳轉條件是標識位。
第四句,jz exit,是跳到exit的意思
注意彙編中exit不是什麼特殊的!exit就是一個自定義的標號。

注意PPT裡的是彙編語句,彙編語句中用二進位制是需要加B的
在這裡插入圖片描述
暫存器AX清零
在這裡插入圖片描述
測試兩個數是否相等,也就是AX和0100 0010是否相等,相等的話跳轉到MATCH

移位指令

移位指令統一的格式:

SAL/SHR/SAR/ROL/ROR/RCL/RCR/SHL reg/mem,1/CL

移位次數可以是1或者CL暫存器的值:為1時二進位制數各個數位只移動移位;如果需要移位的次數大於1,必須將移位次數送CL暫存器,再執行移位指令。

設OPR為運算元,OPR可以是mem和reg
移位次數記為CNT
在這裡插入圖片描述
CNT大於一時,要先把CNT存在CL中,再執行SHL OPR,CL

條件標誌位:
在這裡插入圖片描述
OF的值的解釋有點不清楚,目前來看意思是:最後一次移位後的符號位與最後一次的前一次移位後的符號位不同,OF=1。也就是說,最後一次移位有沒有使最高有效位(或者叫符號位)發生變化,如果變化了,那OF就等於1;如果沒有變化,那麼OF=1.

在這裡插入圖片描述
再提醒一下,計算機中存的都是補碼。
沒有強調是有/無符號數時,用算數或邏輯移動都行。

邏輯左移指令SHL和算術左移指令SAL

在這裡插入圖片描述

SHL SAL
L表示左移
H表示邏輯
A表示算數
當目的運算元為無符號數時,採用邏輯左移指令SHL;當目的運算元為有符號數時,採用算術左移指令SAL
算術左移和邏輯左移的規則是完全一樣的,就是都在右邊添0,相當於原數乘2。
算術左移,可能你會覺得有點奇怪,可以參考這個有效的左移
總之,算術左移和邏輯左移,基本就是一樣的,而且都是可以實現乘2的功能,這個是確定的,你記著就行(也可以看上面的網址理解一下)

邏輯右移指令SHR和算術右移指令SAR

在這裡插入圖片描述
注意右移並不等同於除2,右移是比較複雜的,咱們在這裡先不研究。
無符號數的右移就是補0
有符號數分為正數和負數
正數:右移左邊補0
負數:右移左邊補1
總之就是補符號位的數。

邏輯移位

邏輯移位無論左移右移都補0

左移和右移

算術左移和算術右移主要用來進行有符號數的倍增、減半;
邏輯左移和邏輯右移主要用來進行無符號數的倍增、減半。

帶符號數的移位總是會讓人有點迷茫,先記住這兩句就行,這兩句沒錯。

迴圈移位指令

迴圈移位可以用來做流水小燈

迴圈左移指令ROL和迴圈右移指令ROR

在這裡插入圖片描述
迴圈不帶CF,迴圈的是目的運算元,只是移出的位在CF裡也存一份

帶CF位的迴圈左移指令RCL和迴圈右移指令RCR

在這裡插入圖片描述
帶著CF一起迴圈
請注意帶不帶CF迴圈的區別。

移位指令例項

在這裡插入圖片描述
SAR:算術右移
把DI中的資料指向的記憶體單元中的一個字取出來,右移五次
在這裡插入圖片描述
DS:SI
DS是資料段暫存器
SI表示運算元的偏移地址
0F800→0F8000
因此真正的地址是0F8000+180A=0F980A
將0F980A中的內容取出,值為0064H
即0000 0000 0110 0100
算數右移,說明應該把他當成有符號數,符號位為0,移位補充的應該和符號位保持一致。右移五次後結果應該是0000 0000 0000 0011
也就是0003H
相當於100/32,餘數不要,結果是3

在這裡插入圖片描述

SI=1450H=0001 0100 0101 0000
邏輯左移2位,結果為
0101 0001 0100 0000
即5140H
移位運算一定要化成二進位制再移!看16進位制你是看不出來的!

在這裡插入圖片描述
AX中的內容迴圈左移8次(就還是原來的內容)
再把AX和BX中的內容相或
(我覺得我還是沒明白這個程式的意思)
AX中是0001 1000
迴圈左移八次

如果要求CX*9
可以

MOV AX,CX
MOV BX,CX
MOV CL,3
SAL AX,CL
ADD AX,BX

原理就是先乘8,再加1
那就等於乘9了
如果要求CX*8

MOV AX,CX
MOV CL,3
SAL AX,CL

當然你也可以一次一次的移動,

SAL AX,1

把這條語句重複8次。
注意SAL是算數左移,用來做有符號數的倍增
當然題裡沒明確是是有符號數,其實用兩種都可以