Skip to main content
Engineering LibreTexts

3.10: Shift Operations

  • Page ID
    28491
  • \( \newcommand{\vecs}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \) \( \newcommand{\vecd}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash {#1}}} \)\(\newcommand{\id}{\mathrm{id}}\) \( \newcommand{\Span}{\mathrm{span}}\) \( \newcommand{\kernel}{\mathrm{null}\,}\) \( \newcommand{\range}{\mathrm{range}\,}\) \( \newcommand{\RealPart}{\mathrm{Re}}\) \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\) \( \newcommand{\Argument}{\mathrm{Arg}}\) \( \newcommand{\norm}[1]{\| #1 \|}\) \( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\) \( \newcommand{\Span}{\mathrm{span}}\) \(\newcommand{\id}{\mathrm{id}}\) \( \newcommand{\Span}{\mathrm{span}}\) \( \newcommand{\kernel}{\mathrm{null}\,}\) \( \newcommand{\range}{\mathrm{range}\,}\) \( \newcommand{\RealPart}{\mathrm{Re}}\) \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\) \( \newcommand{\Argument}{\mathrm{Arg}}\) \( \newcommand{\norm}[1]{\| #1 \|}\) \( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\) \( \newcommand{\Span}{\mathrm{span}}\)\(\newcommand{\AA}{\unicode[.8,0]{x212B}}\)

    The final topic covered in this chapter is the shift operations. Shift allow bits to be moved around inside of a register. There are many reasons to do this, particularly when working with low level programs such as device drivers. The major reason this might be done in a HLL is to multiplication and division, but as was stated earlier, multiplication and division using constants should not be implemented by the programmer, as the compiler will automatically generate the best code for the situation. So these operations are difficult to justify in terms of higher level languages. These operations will simply be presented here with an example of multiplication and division by a constant. The reader will have to trust that these operators are useful in assembly and will be used in future chapters.

    There are 2 directions of shifts, a right shift and a left shift. The right shift moves all bits in a register some specified number of spaces to the right, and the left shift moves bits some specified number of spaces to the left.

    The bits that are used to fill in the spaces as the shift occurs are determined by the type of the shift. A logic shift uses zeros (0) to replace the spaces.

    The arithmetic shift replaces the spaces with the high order (left most) bit. In an integer the high order bit determines the sign of the number, so shifting the high order keeps the correct sign for the number12. Note that the sign only matters when doing a right shift, so only the right shift will have an arithmetic shift.

    Finally there is a circular shift (called a rotate in MIPS) that shifts in the bit that was shifted out on the opposite side of the value. For example, when the 4 bit value 0011 is rotated right, a 1 is returned and this 1 is shifted into the right most bit, giving 1001. Likewise when the 4 bit value 0011 is rotated left, a 0 is returned and this 0 is shifted into the right most bit, giving 0110.

    The main use of a rotate command is to allow the programmer to look at each of the 32 bits in a value one at a time, and at the end the register contains the original value. The rol and ror operators (rotate left/right) are pseudo operators, and a circular shift can be implemented using combinations of left and right logical shifts, and an OR operation. This will be explored in the questions at the end of the chapter.

    The following examples show how each of these shifts work.

    Shift left logical 2 spaces: 0x00000004 -> 0x0000000f
    Shift right logical 3 spaces: 0x0000001f -> 0x0000003
    Shift right arithmetic 3 spaces: 0x0000001f -> 0x00000003
    Shift right arithmetic 2 spaces: 0xffffffe1 -> 0xfffffff8
    Rotate right 2 spaces: 0xffffffe1 -> 0x7ffffff8
    Rotate left 2 space: 0xffffffe1 -> 0xffffff87
    

    The program in the following section will implement each of these operations to show how they work.

    The following are the shift operations provided in MIPS.

    • sll (shift left logical) operator. The operator shifts the value in Rt shift amount (shamt) bits to the left, replacing the shifted bits with 0's, and storing the results in Rd. Note that the registers Rd and Rt are used. The numeric value in this instruction is not an immediate value, but a shift amount. Shift values are limited to the range 0..31 in all of the following instructions.

      format:

      sll Rd, Rt, shamt

      meaning:

      Rd <- Rt << shamt

    • sllv (shift left logical variable) operator. The operator shifts the value in Rt bits to the left by the number in Rs, replacing the shifted bits with 0's. The value in Rs should be limited to the range 0..31, but the instruction will run with any value.

      format:

      sllv Rd, Rt, Rs

      meaning:

      Rd <- Rt << Rs

    • srl (shift right logical) operator. The operator shifts the value in Rt shift amount (shamt) bits to the right, replacing the shifted bits with 0's, and storing the results in Rd.

      format:

      srl Rd, Rt, shamt

      meaning:

      Rd <- Rt >> shamt

    • srlv (shift right logical variable) operator. The operator shifts the value in Rt bits to the right by the number in Rs, replacing the shifted bits with 0's. The value in Rs should be limited to the range 0..31, but the instruction will run with any value.

      format:

      srlv Rd, Rt, Rs

      meaning:

      Rd <- Rt >> Rs

    • sra (shift right arithmetic) operator. The operator shifts the value in Rt shift amount (shamt) bits to the right, replacing the shifted bits with sign bit for the number, and storing the results in Rd.

      format:

      sra Rd, Rt, shamt

      meaning:

      Rd <- Rt >> shamt

    • srav (shift right arithmetic variable) operator. The operator shifts the value in Rt bits to the right by the number in Rs, replacing the shifted bits the sign bit for the number. The value in Rs should be limited to the range 0..31, but the instruction will run with any value.

      format:

      srla Rd, Rt, Rs

      meaning:

      Rd <- Rt >> Rs

    • rol (rotate left) pseudo operator. The operator shifts the value in Rt shift amount (shamt) bits to the right, replacing the shifted bits with the bits that were shifted out, and storing the results in Rd.

      format:

      sra Rd, Rt, shamt

      meaning:

      Rd [shamt..0] <- Rt [31..31-shamt+1],

      Rd [31..shamt] <- Rt [31-shamt..0],

      translation:

      srl $at, $Rt, shamt

      sll $Rd, $Rt, shamt

      or $Rd, $Rd, $at

    • rolr (rotate fight) pseudo operator. The operator shifts the value in Rt shift amount (shamt) bits to the right, replacing the shifted bits with the bits that were shifted out, and storing the results in Rd.

      format:

      sra Rd, Rt, shamt

      meaning:

      Rd [31-shamt..shamt] <- Rt [31..shamt],

      Rd [31..31-shamt+1] <- Rt [shamt-1..0],

      translation:

      srl $at, $Rt, shamt

      sll $Rd, $Rt, shamt

      or $Rd, $Rd, $at

    3.10.1 Program illustrating shift operations

    The following program illustrates the shift operations from the previous section.

    Program 3-6: Program illustrating shift operations
    
    # File:        Program3-6.asm
    # Author:      Charles Kann
    # Purpose:     To illustrate various shift operations.
    
    .text
    .globl main
    main:
        #SLL example
        addi $t0, $zero, 4
        sll  $s0, $t0, 2
        addi $v0, $zero, 4
        la $a0, result1
        syscall
        addi $v0, $zero, 1
        move $a0, $s0
        syscall
        
        #SRL example
        addi $t0, $zero, 16
        srl  $s0, $t0, 2
        addi $v0, $zero, 4
        la $a0, result2
        syscall
        addi $v0, $zero, 1
        move $a0, $s0
        syscall
        
        #SRA example
        addi $t0, $zero, 34
        sra  $s0, $t0, 2
        addi $v0, $zero, 4
        la $a0, result3
        syscall
        addi $v0, $zero, 1
        move $a0, $s0
        syscall
        
        #SRA example
        addi $t0, $zero, -34
        sra $s0, $t0, 2     # sra 2 bits, which is division by 4
        addi $v0, $zero, 4  # Output the result
        la $a0, result4
        syscall
        addi $v0, $zero, 1
        move $a0, $s0
        syscall
        
        #rol example
        ori $t0, $zero, 0xffffffe1
        ror $s0, $t0, 2
        li $v0, 4
        la $a0, result6
        syscall
        li $v0, 34
        move $a0, $s0
        syscall
        
        #rol example
        ori $t0, $zero, 0xffffffe1
        rol $s0, $t0, 2
        li $v0, 4
        la $a0, result6
        syscall
        li $v0, 34
        move $a0, $s0
        syscall
        
        addi $v0, $zero, 10 # Exit program
        syscall
    
    .data
    result1: .asciiz "\nshift left logical 4 by 2 bits is "
    result2: .asciiz "\nshift right logical 16 by 2 bits is "
    result3: .asciiz "\nshift right arithmetic 34 by 2 bits is "
    result4: .asciiz "\nshift right arithmetic -34 by 2 bits is "
    result5: .asciiz "\nrotate right 0xffffffe1 by 2 bits is "
    result6: .asciiz "\nrotate left 0xffffffe1 by 2 bits is "
    

    12 This is why it is in some sense incorrect to call the high order bit of an integer a "sign bit". To do division the high order (left-most) bit is replicated to the right. If this high order bit was just a sign bit, it would not be replicated, as the one sign bit only specifies the sign.


    This page titled 3.10: Shift Operations is shared under a CC BY 4.0 license and was authored, remixed, and/or curated by Charles W. Kann III.

    • Was this article helpful?