Jump Operations

This is a contrived example to demonstrate all four jump instructions. In doing so, it violates some principles of MIPS programming. First, the example deliberately jumps back and forth through the main program, an example of "spaghetti code" or unbridled "GO TO" statements. Second, the call/return for the multiply_them routine is non-standard, avoiding the use of ra.

Given that, we see that all the jump instructions work as advertised.

mul/div

The integer multiply and divide instructions are illustrated in the two functions, multiply_them and divide_them. Both invoke the multiply or divide operation similarly:
   mul $v0,$a0,$a1  # v0 = a0*a1
   div $v0,$a0,$a1  # v0 = a0/a1

The multiply operation is done by a single instruction. The divide operation is expanded to a macro.

rotate right and left

The example illustrates two rotate instructions:

    rol    $t1,$t0,$t4  #  t1 = t0 rotated left by t4
    ror    $t2,$t0,$t4  #  r2 = t0 rotated right by t4

The first instruction (rotate left) is a pseudo-instruction expanded into a macro. The second instruction (rotate right) is a machine instruction.

Assembly Source

Download mips3.zip

# mips3.s illustrates jump instructions

    .global main

    .text

    /* This directive tells the assembler don't optimize
     * the order of the instructions and don't insert
     * 'nop' instructions after jumps and branches.
    */
    .set noreorder

/*********************************************************************
 * main()
 * This is where the PIC32 start-up code will jump to after initial
 * set-up.
 ********************************************************************/

.ent main   # directive that marks symbol 'main' as function in ELF output

main:
    li    $a0,24
    li    $a1,4
    j    first
    nop

second:
    jal    divide_them
    nop
    j    done
    nop

first:
    la    $s2,multiply_them
    jalr    $s1,$s2           # This is bad practice (should use ra)
    nop
    move    $v1,$v0
    j    second
    nop
done:
    li    $t0,0xABCD1234
    li    $t4,8
    rol    $t1,$t0,$t4
    ror    $t2,$t0,$t4
    
    jr   $ra
    nop

multiply_them:
    mul $v0,$a0,$a1
    jr  $s1           # this is bad practice (should use ra)
    nop

divide_them:
    div  $v0,$a0,$a1
    jr   $ra
    nop

.end main   #  directive that marks end of 'main' function 
            # and registers size in ELF output

Disassembly Listing

---  C:\pic32\test\mips3.s  ----------------------------------------------------------------------
                                                  1:     # mips3.s illustrates jump instructions
                                                  2:     
                                                  3:         .global main
                                                  4:     
                                                  5:         .text
                                                  6:     
                                                  7:         /* This directive tells the assembler don't optimize
                                                  8:          * the order of the instructions and don't insert
                                                  9:          * 'nop' instructions after jumps and branches.
                                                  10:        */
                                                  11:        .set noreorder
                                                  12:    
                                                  13:    /*********************************************************************
                                                  14:     * main()
                                                  15:     * This is where the PIC32 start-up code will jump to after initial
                                                  16:     * set-up.
                                                  17:     ********************************************************************/
                                                  18:    
                                                  19:    .ent main   # directive that marks symbol 'main' as function in ELF output
                                                  20:    
                                                  21:    main:
9D000018  24040018   addiu       a0,zero,24       22:        li    $a0,24
9D00001C  24050004   addiu       a1,zero,4        23:        li    $a1,4
9D000020  0B40000E   j           0x9d000038       24:        j    first
9D000024  00000000   nop                          25:        nop
                                                  26:    
                                                  27:    second:
9D000028  0F400020   jal         0x9d000080       28:        jal    divide_them
9D00002C  00000000   nop                          29:        nop
9D000030  0B400015   j           0x9d000054       30:        j    done
9D000034  00000000   nop                          31:        nop
                                                  32:    
                                                  33:    first:
9D000038  3C129D00   lui         s2,0x9d00        34:        la    $s2,multiply_them
9D00003C  26520074   addiu       s2,s2,116
9D000040  02408809   jalr        s1,s2            35:        jalr    $s1,$s2           # This is bad practice (should use ra)
9D000044  00000000   nop                          36:        nop
9D000048  00401821   addu        v1,v0,zero       37:        move    $v1,$v0
9D00004C  0B40000A   j           0x9d000028       38:        j    second
9D000050  00000000   nop                          39:        nop
                                                  40:    done:
9D000054  3C08ABCD   lui         t0,0xabcd        41:        li    $t0,0xABCD1234
9D000058  35081234   ori         t0,t0,0x1234
9D00005C  240C0008   addiu       t4,zero,8        42:        li    $t4,8
9D000060  000C4823   subu        t1,zero,t4       43:        rol    $t1,$t0,$t4
9D000064  01284846   rotrv       t1,t0,t1                    
9D000068  01885046   rotrv       t2,t0,t4         44:        ror    $t2,$t0,$t4
                                                  45:        
9D00006C  03E00008   jr          ra               46:        jr   $ra
9D000070  00000000   nop                          47:        nop
                                                  48:    
                                                  49:    multiply_them:
9D000074  70851002   mul         v0,a0,a1         50:        mul $v0,$a0,$a1
9D000078  02200008   jr          s1               51:        jr  $s1           # this is bad practice (should use ra)
9D00007C  00000000   nop                          52:        nop
                                                  53:    
                                                  54:    divide_them:
9D000080  00A001F4   teq         a1,zero          55:        div  $v0,$a0,$a1
9D000084  0085001A   div         a0,a1
9D000088  2401FFFF   addiu       at,zero,-1
9D00008C  14A10002   bne         a1,at,0x9d000098
9D000090  3C018000   lui         at,0x8000
9D000094  008101B4   teq         a0,at
9D000098  00001012   mflo        v0
9D00009C  03E00008   jr          ra               56:        jr   $ra
9D0000A0  00000000   nop                          57:        nop


Maintained by John Loomis, last updated 18 July 2008