© Jo Van Hoey 2019
J. Van HoeyBeginning x64 Assembly Programminghttps://doi.org/10.1007/978-1-4842-5076-1_16

16. Bit Operations

Jo Van Hoey1 
(1)
Hamme, Belgium
 

We have already done bit operations in Chapter 9 on integer arithmetic: shift arithmetic sar and sal are bit operations, shifting bits right or left. Also, the and instruction for aligning the stack covered in the previous chapter is a bit operation.

Basics

In the following example program, we are building a custom C function called printb to print a string of bits. For convenience, it separates the string of 64 bits into 8 bytes, with 8 bits each. As an exercise, after you finish this chapter, take a look at the C code, and you should be able to write an assembler program to build a string of bits.

Listing 16-1, Listing 16-2, and Listing 16-3 show the example code for the bit operations in assembly, the C printb program, and the makefile, respectively.
; bits1.asm
extern printb
extern printf
section .data
      msgn1 db    "Number 1",10,0
      msgn2 db    "Number 2",10,0
      msg1  db    "XOR",10,0
      msg2  db    "OR",10,0
      msg3  db    "AND",10,0
      msg4  db    "NOT number 1",10,0
      msg5  db    "SHL 2 lower byte of number 1",10,0
      msg6  db    "SHR 2 lower byte of number 1",10,0
      msg7  db    "SAL 2 lower byte of number 1",10,0
      msg8  db    "SAR 2 lower byte of number 1",10,0
      msg9  db    "ROL 2 lower byte of number 1",10,0
      msg10 db    "ROL 2 lower byte of number 2",10,0
      msg11 db    "ROR 2 lower byte of number 1",10,0
      msg12 db    "ROR 2 lower byte of number 2",10,0
      number1     dq    -72
      number2     dq    1064
section .bss
section .text
      global main
main:
push  rbp
mov   rbp,rsp
; print number1
      mov   rsi, msgn1
      call  printmsg
      mov   rdi, [number1]
      call  printb
; print number2
      mov   rsi, msgn2
      call  printmsg
      mov   rdi, [number2]
      call  printb
; print XOR (exclusive OR)------------------------
      mov   rsi, msg1
      call  printmsg
; xor and print
      mov   rax,[number1]
      xor   rax,[number2]
      mov   rdi, rax
      call  printb
; print OR ---------------------------------------
      mov   rsi, msg2
      call  printmsg
; or and print
      mov   rax,[number1]
      or    rax,[number2]
      mov   rdi, rax
      call  printb
; print AND  ---------------------------------------
      mov   rsi, msg3
      call  printmsg
; and and print
      mov   rax,[number1]
      and   rax,[number2]
      mov   rdi, rax
      call  printb
; print NOT  ---------------------------------------
      mov   rsi, msg4
      call  printmsg
; not and print
      mov   rax,[number1]
      not   rax
      mov   rdi, rax
      call  printb
; print SHL  (shift left----------------------------
      mov   rsi, msg5
      call  printmsg
; shl and print
      mov   rax,[number1]
      shl   al,2
      mov   rdi, rax
      call  printb
; print SHR  (shift right)--------------------------
      mov   rsi, msg6
      call  printmsg
;shr and print
      mov   rax,[number1]
      shr   al,2
      mov   rdi, rax
      call  printb
; print SAL  (shift arithmetic left)----------------
      mov   rsi, msg7
      call  printmsg
; sal and print
      mov   rax,[number1]
      sal   al,2
      mov   rdi, rax
      call  printb
; print SAR  (shift arithmetic right)----------------
      mov   rsi, msg8
      call  printmsg
; sar and print
      mov   rax,[number1]
      sar   al,2
      mov   rdi, rax
      call  printb
; print ROL  (rotate left)---------------------------
      mov   rsi, msg9
      call  printmsg
; rol and print
      mov   rax,[number1]
      rol   al,2
      mov   rdi, rax
      call  printb
      mov   rsi, msg10
      call  printmsg
      mov   rax,[number2]
      rol   al,2
      mov   rdi, rax
      call  printb
; print ROR  (rotate right)---------------------------
      mov   rsi, msg11
      call  printmsg
; ror and print
      mov   rax,[number1]
      ror   al,2
      mov   rdi, rax
      call  printb
      mov   rsi, msg12
      call  printmsg
      mov   rax,[number2]
      ror   al,2
      mov   rdi, rax
      call  printb
leave
ret
;-----------------------------------------------------
printmsg:    ; print the heading for every bit operation
section .data
      .fmtstr            db      "%s",0
section .text
      mov   rdi,.fmtstr
      mov   rax,0
      call  printf
      ret
Listing 16-1

bits1.asm

// printb.c
#include <stdio.h>
void printb(long long n){
      long long s,c;
      for (c = 63; c >= 0; c--)
      {
      s = n >> c;
            // space after every 8th bit
            if ((c+1) % 8 == 0) printf(" ");
            if (s & 1)
                  printf("1");
            else
                  printf("0");
      }
      printf(" ");
}
Listing 16-2

printb.c

# makefile for bits1 and printb
bits1: bits1.o printb.o
      gcc -g -o bits1 bits1.o printb.o -no-pie
bits1.o: bits1.asm
      nasm -f elf64 -g -F dwarf bits1.asm -l bits1.lst
printb: printb.c
      gcc -c printb.c
Listing 16-3

makefile for bits1 and printb

Build and run the program and study the output. If you are using SASM, do not forget to compile the printb.c file first and then add the object file in the Linking Options, as mentioned when discussing external functions in Chapter 14.

This is quite a long program. Fortunately, the code is not complicated. We’ll show how the different bit operation instructions work. Use the output shown in Figure 16-1 to guide you through the code.
../images/483996_1_En_16_Chapter/483996_1_En_16_Fig1_HTML.jpg
Figure 16-1

bits1.asm output

First note the binary representation of number1 (-72); the 1 in the most significant bit indicates a negative number.

The instructions xor, or, and, and not are pretty simple; they work as explained in Chapter 5. Experiment with different values to see how it works.

For shl , shr , sal , and sar , we use the lower byte of rax to illustrate what is going on. With shl, bits are shifted to the left and zeros are added to the right of al; the bits are moved to the left, and the bits that move to the left of the 8th bit are simply discarded. With shr, bits are shifted to the right and zeros are added to the left of al. All bits are moved to the right, and bits that move to the right of the least significant bit are dropped. When you are stepping through the program, keep an eye on the flag registers, especially the sign register and the overflow register.

The arithmetic left shift, sal, is exactly the same as shl; it multiplies the value. The arithmetic shift right, sar, division, is different from shr. Here we have what is called sign extension. If the leftmost bit in al is a 1, al contains a negative value. To do the arithmetic correctly, when shifting right, 1s instead of 0s are added to the left in case of a negative value. This is called sign extension.

Rotate left, rol , removes the leftmost bit, shifts left, and adds the removed bits to the right. Rotate right, ror , works in a similar way.

Arithmetic

Let’s do some deep dive into shifting arithmetic. Why are there two types of shift left and two types of shift right? When doing arithmetic with negative values, shift instructions can give you wrong results, because sign extension needs to be taken into account. That is why there are arithmetic shift instructions and logical shift instructions.

Study the example in Listing 16-4.
; bits2.asm
extern printf
section .data
      msgn1 db    "Number 1 is = %d",0
      msgn2 db    "Number 2 is = %d",0
      msg1  db    "SHL 2 = OK multiply by 4",0
      msg2  db    "SHR 2 = WRONG divide by 4",0
      msg3  db    "SAL 2 = correctly multiply by 4",0
      msg4  db    "SAR 2 = correctly divide by 4",0
      msg5  db    "SHR 2 = OK divide by 4",0
      number1     dq    8
      number2     dq    -8
      result      dq    0
section .bss
section .text
      global main
main:
push  rbp
mov   rbp,rsp
;SHL-------------------------------------------------
;positive number
      mov   rsi, msg1
      call  printmsg         ;print heading
      mov   rsi, [number1]
      call  printnbr         ;print number1
      mov   rax,[number1]
      shl   rax,2      ;multiply by 4 (logic)
      mov   rsi, rax
      call  printres
;negative number
      mov   rsi, msg1
      call  printmsg         ;print heading
      mov   rsi, [number2]
      call  printnbr         ;print number2
      mov   rax,[number2]
      shl   rax,2      ;multiply by 4 (logic)
      mov   rsi, rax
      call  printres
;SAL-------------------------------------------------
;positive number
      mov   rsi, msg3
      call  printmsg         ;print heading
      mov   rsi, [number1]
      call  printnbr         ;print number1
      mov   rax,[number1]
      sal   rax,2      ;multiply by 4 (arithmetic)
      mov   rsi, rax
      call  printres
;negative number
      mov   rsi, msg3
      call  printmsg         ;print heading
      mov   rsi, [number2]
      call  printnbr         ;print number2
      mov   rax,[number2]
      sal   rax,2      ;multiply by 4 (arithmetic)
      mov   rsi, rax
      call  printres
;SHR-------------------------------------------------
;positive number
      mov   rsi, msg5
      call  printmsg         ;print heading
      mov   rsi, [number1]
      call  printnbr         ;print number1
      mov   rax,[number1]
      shr   rax,2      ;divide by 4 (logic)
      mov   rsi, rax
      call  printres
;negative number
      mov   rsi, msg2
      call  printmsg         ;print heading
      mov   rsi, [number2]
      call  printnbr         ;print number2
      mov   rax,[number2]
      shr   rax,2      ;divide by 4 (logic)
      mov   [result], rax
      mov   rsi, rax
      call  printres
;SAR-------------------------------------------------
;positive number
      mov   rsi, msg4
      call  printmsg         ;print heading
      mov   rsi, [number1]
      call  printnbr         ;print number1
      mov   rax,[number1]
      sar   rax,2      ;divide by 4 (arithmetic)
      mov   rsi, rax
      call  printres
;negative number
      mov   rsi, msg4
      call  printmsg         ;print heading
      mov   rsi, [number2]
      call  printnbr         ;print number2
      mov   rax,[number2]
      sar   rax,2      ;divide by 4 (arithmetic)
      mov   rsi, rax
      call  printres
leave
ret
;-----------------------------------
printmsg:              ;print the title
      section .data
            .fmtstr db 10,"%s",10,0 ;format for a string
      section .text
            mov   rdi,.fmtstr
            mov   rax,0
            call  printf
      ret
;-----------------------------------
printnbr:              ;print the number
      section .data
            .fmtstr db "The original number is %lld",10,0
      section .text
            mov   rdi,.fmtstr
            mov   rax,0
            call  printf
      ret
;-----------------------------------
printres:              ;print the result
      section .data
            .fmtstr db "The resulting number is %lld",10,0
      section .text
            mov   rdi,.fmtstr
            mov   rax,0
            call  printf
      ret
Listing 16-4

bits2.asm

Use the output shown in Figure 16-2 to analyze the code.
../images/483996_1_En_16_Chapter/483996_1_En_16_Fig2_HTML.jpg
Figure 16-2

bits2.asm output

Notice that shl and sal give the same results, also with negative numbers. But be careful; if shl would put a 1 in the leftmost bit instead of a 0, the result would become negative and wrong.

The instructions shr and sar give the same result only when the numbers are positive. The arithmetic result when using shr with negative numbers is simply wrong; that is because there is no sign extension with shr.

Conclusion: when you are doing arithmetic, use sal and sar.

Why would you need shifting when there are straightforward instructions such as multiply and divide? It turns out the shifting is much faster than the multiplying or dividing instructions. In general, bit instructions are very fast; for example, xor rax, rax is faster than mov rax,0.

Summary

In this chapter, you learned about the following:
  • Assembly instructions for bit operations

  • Difference between logical and arithmetic shift instructions

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
13.59.79.176