Hi! Welcome to the fifth chapter of this series. Now, we will discuss about bit shifting and rolling in assembly. We also revisit the bit masking stuff too.
To illustrate bit-shifting, let's suppose we have AL = 11010011. Shifting operation can be done in two direction, to the left or to the right. If we shift AL to the left one position, we will have AL = 10100110. Notice the difference?
AL = 11010011 ; shifting left 1 position: AL = 10100110
Oh, so shifting left one position means take one bit at the left, then shift the remaining bits, then add one 0 at the end. So, shifting left by 2 positions will yield 01001100, shifting left by 3 will result in 10011000, and so on.
Shifting right is analoguous. 11010011 shifted right one position is 01101001; by 2 position is 00110100, by 3 position is 00011010, and so on. Easy right?
Now, what is the instruction to do so? The syntax is:
shl x, y ; --> means : x is shifted left by y positions shr x, y ; --> means : x is shifted right by y positions
The x and y usage is just like add or sub, you can have registers, variables or constants. Of course the x part cannot be a constant. However, in 8086 processor, if you subtitute y as a constant, it must be a 1, no other numbers are allowed. In 8086, if y is a register, then it must be CL. These restrictions are lifted in 80286 or newer processors.
What happened to the missing bits that get shifted out? Good question. They are not missing immediately. The carry flag will hold the last shifted-out bit. To illustrate it:
mov al, 11010011b shl al, 1 ; --> AL = 10100110b, carry flag (CF) = 1 shl al, 1 ; --> AL = 01001100b, CF = 1 shl al, 1 ; --> AL = 10011000b, CF = 0
Similarly:
mov al, 11010011b shl al, 3 ; --> AL = 10011000b, CF = 0
This may be handy to check whether the latest bit is 0 or 1 by testing carry flag using jc instruction. This testing instruction will be discussed in the next chapter.
Bit rolling is similar to bit-shifting. Instead of shifted out, the bits gets rolled back. For example: Let's say AL = 11010011b.
AL = 11010011b ; rolling left 1 position: AL = 10100111b ; rolling left 1 more position: AL = 01001111b
Ah, when rolling left, the value of first will be inserted back at the end of the bits. Rolling to the right is similar. Instead of going to the left side, it goes to the right side. The carry flag is consequentially inserted at the beginning of the bits.
The syntax for bit rolling is:
rol x, y ; --> means : x is rolled left by y positions ror x, y ; --> means : x is rolled right by y positions
The usage is similar to bit shifting. The limitations on 8086 is also similar, and is also lifted up in 80286 or newer processors.
There is another variant on rolling bits, using carry flag. These instructions are rarely used, so you can skip these if you like. Rolling bits using carry flag is done by rcl and rcr instruction for left and right rolling respectively. It behaves pretty much like rol and ror. To explain it better, let's examine the following example: Let's say AL = 11010011b and the carry flag (CF) is 0.
CF = 0 AL = 11010011b ; rolling left 1 position: CF = 1 AL = 10100110b ; rolling left 1 more position: CF = 1 AL = 01001101b
The usage of rcl and rcr is similar.
Now you understand bit shifting. The question in the last chapter is that how can we extract or set the middle 4 bits (or any bits in the middle of a bit sequence). The answer is using bit-shifting. Let's suppose AL = 00101101b. Let's say that we're interested in extracting the middle 4 bits. So, we make the mask in AH, which is equal to 00111100. Remember that we should set the mask on all interesting bits into 1 and the other must be 0. To extract the bits out, we use the and operation, as follows:
mov al, 00101101b mov ah, 00111100b and al, ah ; --> now al = 00101100b
Since the data is hanging in the middle by 2 bits, we will then shift AL 2 positions to the right. So, the program becomes:
mov al, 00101101b mov ah, 00111100b and al, ah ; --> now al = 00101100b shr al, 2 ; --> now al = 00001011b
Of course that the snippet above assumes 80286 or better (or alternatively you can do shr al, 1 twice for 8086). Analoguously, if you are interested in only the middle 2 bits, the mask in AH should be 00011000b and you have to shift right by 3 positions.
Putting the data back is just similar. Suppose you want to put the data in lower 4 bits of CL, which is equal to 01100010b. Then, you'll do as follows:
mov al, 00101101b mov cl, 01100010b mov ah, 11000011b and al, ah ; --> now al = 00000001b mov ah, 00001111b and cl, ah ; --> now cl = 00000010b shl cl, 2 ; --> now cl = 00001000b or al, cl ; --> now al = 00001011b
Note that I shift left CL by 2 in order to make the desired data (i.e. 0010) is placed right in the middle 4 bits.
OK, I think that's all for now. Bit shifting is more useful than bit rolling and more often used in programming. Bit rolling is usually used in testing bits and encryption. But it is usually not practical. Note that I omit the sar instruction which is used for shifting arithmatic right. This one is not quite useful, except if you'd like to do tricks in quick division in negative numbers. I'll try to cover more eccentric instructions later in lesson 2 or 3.
I admit that bit masking is a bit confusing at first. However, this is very important in assembly programming. I'll try to fix this chapter as soon as I got an input from you. See you next time.
Chapter 6
News Page
x86 Assembly Lesson 1 index
Contacting Me
Roby Joehanes © 2001