彙編之位操作指令
彙編之位操作指令
前言
位運算的特點是運算單元是位,一個位的變化不會對旁邊位產生影響。
邏輯運算指令
邏輯運算指令是位運算指令的子集,邏輯運算指的就是位運算指令中的與或非
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也有判斷奇偶的功能。
可以用來判斷最高位是否為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是算數左移,用來做有符號數的倍增
當然題裡沒明確是是有符號數,其實用兩種都可以