Bitwise Operation

Part 2 -- Shifting and Rolling




Welcome

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.

 

Bit Shifting

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

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.

 

Bit Masking Revisited

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.

 

Closing

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.

 


Where to go

Chapter 6
News Page
x86 Assembly Lesson 1 index
Contacting Me


Roby Joehanes © 2001