匯編語(yǔ)言允許程序員對(duì)數(shù)據(jù)的單個(gè)比特位進(jìn)行操作。一個(gè)最常見(jiàn)的的位操作稱為移位。移位操作移動(dòng)某一個(gè)數(shù)據(jù)的比特位的位置。移位可以是向左移(也就是:向最高有效位移動(dòng)),也可以向右移(最低有效位)。
邏輯移位
邏輯移位是移位中最簡(jiǎn)單的類型。它以一種最直接的方式進(jìn)行移位操作。圖3.1展示了一個(gè)字節(jié)的移位操作的例子。
注意:新進(jìn)來(lái)的比特位總是為0。SHL 和SHR 指令分別用來(lái)執(zhí)行邏輯左移和邏輯右移。這些指令允許你移動(dòng)任意的位數(shù)。位數(shù)可以是一個(gè)常量,也可以是儲(chǔ)存在CL寄存器的值。最后從數(shù)據(jù)中移出的比特位儲(chǔ)存在進(jìn)位標(biāo)志位中。這有一些代碼例子:
移位的應(yīng)用
快速的乘法和除法是移位操作最普遍的應(yīng)用?;貞浽谑M(jìn)制系統(tǒng)中,乘以和除以10的幾次方是非常簡(jiǎn)單的,只是移動(dòng)位而已。在二進(jìn)制中,乘以和除以2的幾次方也是一樣的。例如:要得到二進(jìn)制數(shù)10112(或十進(jìn)制11)的兩倍,只需向左移動(dòng)一位,得到101102 (或22)。一個(gè)除以2的幾次方的除法的商相當(dāng)于一個(gè)右移操作的結(jié)果。僅僅是除以2,向右移動(dòng)一位;除以4(22),向右移動(dòng)2位;除以8(23,向右移動(dòng)3位,等等。移位指令非?;A(chǔ)而且比功能相同的MUL 和DIV 指令執(zhí)行要快得多!
實(shí)際上,邏輯移位只可以用于無(wú)符號(hào)數(shù)的乘法和除法。一般它們不能應(yīng)用于有符號(hào)數(shù)。考慮兩個(gè)字節(jié)的數(shù)值FFFF(有符號(hào)時(shí)為?1)。如果它向右邏輯移動(dòng)一位,結(jié)果是7FFF,也就是+32; 767!另一種類型的移位操作可以用在有符號(hào)數(shù)上。
算術(shù)移位
這些移位操作是為允許有符號(hào)數(shù)能快速地執(zhí)行乘以和除以2的幾次方的操作而設(shè)計(jì)的。它們保證符號(hào)位能被正確對(duì)待。
SAL 算術(shù)左移(Shift Arithmetic Left) - 這條指令只是SHL的同義詞。它實(shí)際上被編譯成與SHL一樣的機(jī)器代碼。只要符號(hào)位沒(méi)有因移位而改變,結(jié)果就將是正確的。
SAR 算術(shù)右移(Shift Arithmetic Right) - 這是一條新的指令,它不會(huì)移動(dòng)操作數(shù)的符號(hào)位(也就是: 最高有效位)。其它位被正常移動(dòng),除了從左邊新進(jìn)來(lái)的位通過(guò)復(fù)制符號(hào)位(也就是說(shuō),如果符號(hào)位為1,那么新的位值也同樣為1)得到外。因此,如果一個(gè)字節(jié)使用這條指令來(lái)移位,只有低7位會(huì)被移動(dòng)。就像其它移位指令一樣,最后移出的位儲(chǔ)存在進(jìn)位標(biāo)志位中。
循環(huán)移位
循環(huán)移位指令像邏輯指令一樣運(yùn)作,除了把從數(shù)據(jù)的一端移出的比特位又移入到另一端外。因此,數(shù)據(jù)好像被當(dāng)作一個(gè)循環(huán)結(jié)構(gòu)體一樣對(duì)待。ROL和ROR 是兩個(gè)最簡(jiǎn)單的循環(huán)移位指令,它們分別執(zhí)行左移和右移操作。就像其它移位指令一樣,這些移位指令把循環(huán)移出的最后一個(gè)比特位復(fù)制到進(jìn)位標(biāo)志位中。
有兩個(gè)額外的循環(huán)指令用來(lái)在數(shù)據(jù)和進(jìn)位標(biāo)志位之間移動(dòng)比特位,它們稱為RCL 和RCR。例如,如果AX寄存器用這些指令來(lái)移位,那么有17位用來(lái)得到AX,進(jìn)位標(biāo)志位也包括在循環(huán)中。
簡(jiǎn)單應(yīng)用
這有一個(gè)代碼小片斷,它用來(lái)計(jì)算在EAX寄存器里\on"(也就是: 1)的比特位有多少個(gè)。
上面的代碼毀掉了在EAX中的初值(循環(huán)之后,EAX的值為0)。如果你想保留EAX中的值,那么用rol eax, 1替換第四行即可。
更多建議: