Sunday, March 29, 2020

trap, break, jalr and jr MIPS instructions

This is sample MIPS assembler code demonstrating the behaviour of the teq, teqi, tge, tgeu, tgei, tgeiu, tlt, tlti, tltiu, tltu, tne, tnei, jr, jalr, lw, sw, break instructions. These instructions were implemented and/or improved in EzMIPS v.9.1.0. The code is fully commented.

Launch EzMIPS, copy the following MIPS code and paste it into EzMIPS, the MIPS assembler editor & simulator. Assemble, Run.


# teq, teqi, tge, tgeu, tgei, tgeiu, tlt, tlti, tltiu, tltu, tne, tnei, jr, jalr, lw, sw, break

main:

# ................................................................ #

    #break           # Runtime exception at 0x00400000: break instruction executed; code: 0
    #break 192       # Runtime exception at 0x00400000: break instruction executed; code: 192
    #break 0x08      # Runtime exception at 0x00400000: break instruction executed; code: 8
    #break 0x123  6  # invalid <break> instruction syntax

# ................................................................ #
    
    #la $ra, end
    #addi $ra, $ra, 1
    #jr $ra          # invalid program counter <0x00400011>

# ................................................................ #

    #li $5, 0x00400001
    #jalr $5         # invalid program counter <0x00400001>

# ................................................................ #

    #jalr $6, $7     # invalid program counter <0x00000000>
    
# ................................................................ #

    # following 2 lines used to crash in previous versions, fixed!
    #lw
    #sw

# ................................................................ #

    # following line used to crash in previous versions, fixed!
    # lw $10, 4($t7)

# ................................................................ #

    #lw $11, N      # should be ok, yes it is!
    #lw $11, main   # <main> is an uknown variable name

# ................................................................ #

    # Runtime exception: Cannot read directly from this address <0x00400000>
    #la $10, main
    #lw $11, ($10)

# ................................................................ #

    # Error | Runtime exception: Cannot write directly to this address <0x00000004>
    #sw $10, 4($t7)

# ................................................................ #

    #teq $12, $20   # Error | line 55    | Runtime exception (trap) at <0x00400000>

    #li $13, -10
    #teqi $13, -10  # Error | line 58    | Runtime exception (trap) at <0x00400008>

    #li $14, 0xffffffff
    #li $15, 0
    #tge $14, $15         # should NOT trap
    #tgeu $14, $15        # should TRAP

    #li $18, -1
    #tgei $18, 1          # should NOT trap
    #tgeiu $18, 1         # should TRAP
    
    #li $14, 0
    #li $25, -1
    #tlt $14, $25         # should NOT trap
    #tltu $14, $25        # should TRAP

# .............................................................. #

    #tlti $0, -1          # should NOT trap
    #tltiu $0, -1         # should TRAP

# .............................................................. #

    #li $14, 123
    #li $15, 124
    #tne $14, $15         # should TRAP
    #tnei $14, 128        # should TRAP

# .............................................................. #

end:
    sll $0, $0, 0

    #sync

.data

Y: .word 0xff
N: .word 0x14

# ................................................................ #

Please let me know of any suggestions or bugs regarding the code above.

Regards,

Antonis

Thursday, March 26, 2020

.align directive demo code in MIPS

This is a sample MIPS assembler code demonstrating the behaviour of the .align directive in a MIPS assembler program. The code is fully commented.

Launch EzMIPS, copy the following MIPS code and paste it into EzMIPS, the MIPS assembler editor & simulator. Assemble, Run.

# ---------- demonstration of the .align directive in MIPS  -------------- #

# Default section: .text

#.align 4                   # .align directive not allowed in text segment

# ------------------------------------------------------------------------ #

.data

# Default behaviour: 
# .................. 

# Automatic alignment of .half, .word, .float, and .double directives

# ........................................................................ #

#.align -3                  # invalid alignment value <-3>
#.align                     # no alignment value specified


var01: .byte 1, 2, 'Z'      # 0x10010000: 1, 0x10010001: 2, 0x10010002: 0x5a 
str01: .asciiz "Hello\n"    # 0x10010003: Hello\n
var02: .word 0x12345678     # 0x1001000c: 0x12345678
var03: .byte 0x11           # 0x10010010: 0x11

# ........................................................................ #

.align 2                    # align the next variable on the
                            # next word boundary
var04: .half 0xffff         # 0x10010014: 0xffff

# ...................................................................... #

var05: .byte 0xaa           # no alignment specified
                            # 0x10010016: 0xaa
# ...................................................................... #

.align 4                    # align the next variable on the
                            # next 2^4 = 16 boundary

var06: .half 0xbbbb
                            # 0x10010020: 0xbbbb
# ...................................................................... #

.align 0                    # .align 0 turns off automatic alignment of
                            # .half, .word, .float, and .double directives
                            # until the next .data or .kdata directive.

# ...................................................................... #

#                      NO AUTOMATIC ALIGNMENT FROM NOW ON                #

# ...................................................................... #

.align 7                    # align the next variable on the
                            # next 2^7 = 128 boundary

var19: .byte 0xcc           # 0x10010080: 0xcc

# ...................................................................... #

var07: .word 0xffffffff     # We said: NO AUTOMATIC ALIGNMENT
                            # 0x10010081: 0xffffffff

var08: .word 0xaaaaaaaa     # We said: NO AUTOMATIC ALIGNMENT
                            # 0x10010085: 0xaaaaaaaa
# ...................................................................... #

.align 1                    # align the next variable on the
                            # next halfword boundary

var09: .byte 0xbb           # 0x1001008a: 0xbb

# ...................................................................... #

var11: .word 0xdddddddd     # We said: NO AUTOMATIC ALIGNMENT
                            # 0x1001008b: 0xdddddddd

var12: .space 20            # 0x1001008f: -

.align 1
var13: .byte 0x99           # align the next variable on the
                            # next halfword boundary
                            # 0x100100a4: 0x99
# ---------------------------------------------------------------------- #
.text

main:
    #.align 2               # .align directive not allowed in text segment
    sll $zero, $zero, 0

# ---------------------------------------------------------------------- #

.data

# Default behaviour: 
# .................. 

# Automatic alignment of .half, .word, .float, and .double directives

# This is a NEW .data secttion so: AUTOMATIC ALIGNMENT from noe on
# ie forget the NO AUTOMATIC ALIGNMENT of the previous .data section!
# ...................................................................... #

var14: .word 0xeeeeeeee     # 0x100100a8: 0xeeeeeeee

# ---------------------------------------------------------------------- #

Please let me know of any suggestions or bugs regarding the code above.

Regards,

Antonis

Compute the sum of N consecutive numbers

This is a sample MIPS assembler code to compute the sum of N consecutive numbers, where N is an integer entered by the user. The code is fully commented.

Launch EzMIPS, copy the following MIPS code and paste it into EzMIPS, the MIPS assembler editor & simulator. Assemble, Run.

# --- compute the sum of N consecutive integers: 1 + 2 + 3 + ... + N --- #

.data

szNumbeOfIntegers: .asciiz "Enter number of integers (N): "
szSumIs:           .asciiz "Sum = "
szLF:              .asciiz "\n"

# ---------------------------------------------------------------------- #

.text

main:

# ...................................................................... #
    
    # Print "Enter number of integers (N): "
    li $v0, 4                      # print string syscall code = 4
    la $a0, szNumbeOfIntegers      # load address of szNumbeOfIntegers
    syscall                        # print it!

# ...................................................................... #

    # Get N from user
    li $v0, 5                      # read integer syscall code = 5
    syscall                        # get it!
    move $t0, $v0                  # keep N in $t0

# ...................................................................... #

    # Initialize registers
    ori $t1, $zero, 0              # initialize counter $t1=0
    ori $t2, $zero, 0              # initialize sum $t2=0

# ...................................................................... #

    # perform the addition!
loop:
    addi $t1, $t1, 1               # $t1 = $t1 + 1 (counter++)
    add $t2, $t2, $t1              # $t2 = $t2 + $t1 (sum = sum + counter)
    bne $t0, $t1, loop             # if conter != N, loop

# ...................................................................... #

    # Print "Sum = "
    li $v0, 4                      # print string syscall code = 4
    la $a0, szSumIs                # load address of szSumIs
    syscall                        # print it!

# ...................................................................... #

    # Print integer sum (=$t2)
    li $v0, 1                      # print integer syscall code = 1
    move $a0, $t2
    syscall                        # print it!

# ...................................................................... #

    # Print new line
    li $v0, 4                      # print string syscall code = 4
    la $a0, szLF                   # load address of szLF
    syscall                        # print it!         

# ...................................................................... #

    li $v0, 10                     # exit syscall = 10
    syscall                        # exit

# ---------------------------------------------------------------------- #

Please let me know of any suggestions or bugs regarding the code above.

Regards,

Antonis

Tuesday, March 24, 2020

Absolute value of the diferrence of two numbers

This is a sample MIPS assembler code to read two 32-bit numbers from memory and calculate the absolute value of their diferrence (ie |B-A|), store the result into memory and, finally, print it. The code is fully commented.

Launch EzMIPS, copy the following MIPS code and paste it into EzMIPS, the MIPS assembler editor & simulator. Assemble, Run.

# ------------------------------------------------------------------------- #
# Reads word A from from word variable var01
# Reads word B from from word variable var02
# Caclculate |B-A| and store the result into word variable var03
# ------------------------------------------------------------------------- #

.data
var01: .word 116            # address =0x10010000
var02: .word 17             # address =0x10010004
var03: .word 00             # address =0x10010008

var04: .asciiz "|B-A| = "

# expected output:
# |B-A| = 99

# ......................................................................... #

.text

    la $t1, var01           # Load address of var01

    lw $a0, 0($t1)          # read A from var01 into register $a0
    lw $a1, 4($t1)          # read B from var02 into register $a1
                            # (var02 address = address of var01 + 4)

    sub $t4, $a1, $a0       # $t4 = $a1 - $a0
    bgez $t4, positive      # if $t4 >= 0, branch to ‘sw’ instruction
    sub $t4, $a0, $a1       # else, $t4 = $a0 - $a1

positive:
    sw $t4, 8($t1)          # store register $t4 value, |B-A|, into var03
                            # (var03 address = address of var01 + 8)
# ......................................................................... #
    
    # print "|B-A| = "
    la $a0, var04           # Load address of var04
    li $v0, 4               # syscall code for print string
    syscall                 # print it!

    # print integer result of |B-A|
    move $a0, $t4
    li $v0, 1               # syscall code for print integer
    syscall                 # print it!

# ------------------------------------------------------------------------- #

Please let me know of any suggestions or bugs regarding the code above.

Regards,

Antonis

Fibonacci sequence in MIPS

This is a sample MIPS assembler code to calculate the fibonacci sequence of the first 20 numbers, store them in an array of words and, finally, print them. The code is fully commented.

Launch EzMIPS, copy the following MIPS code and paste it into EzMIPS, the MIPS assembler editor & simulator. Assemble, Run.

# ---------------------------------------------------------------- #
# The Fibonacci sequence is the sequence of numbers given
# by an+2 = an+1 + an ie 1, 1, 2, 3, 5, 8, 13, 21,...

# ---------------------------------------------------------------- #

.data

# .... array of words to hold the first 20 Fibonacci numbers ..... #

Array: .word 0,0,0,0,0,0,0,0,0,0
       .word 0,0,0,0,0,0,0,0,0,0

szComma:  .asciiz ", "

# ---------------------------------------------------------------- #

.text
main:

    ori $t6, $zero, 1       # set t6 to 1

    la $t0, Array           # $t0 holds the memory address
                            # of the 1st array element
    
    sw $t6, ($t0)           # set the 1st term to 1
    sw $t6, 4($t0)          # set the 2nd term to 1

    addiu $t6, $t0, 80      # $t6 now holds the address after
                            # the 20th array element!

    addiu $t0, $t0, 8       # $t0 now holds the address of
                            # the 3rd array element

# ................................................................ #

loop:
    addi  $t4, $t0, -4      # $t4 holds the address of the 
                            # last array element SO FAR

    addi  $t3, $t0, -8      # $t4 holds the address of the array
                            # element before last element SO FAR



    lw $t2, ($t4)           # get the last element

    lw $t1, ($t3)           # get the element before the
                            # last element


    add $t5, $t1, $t2       # Add the two last elements together...

    sw $t5, ($t0)           # store the result AFTER the currently
                            # last element


    addi $t0, $t0, 4        # move to next element of the Array

    slt $at, $t0, $t6       # Remember: $t6 holds the address after
                            # the 30th array element!

    bne $at, $0, loop       # If not past the end of Array, repeat

# ................................................................ #

# print the first 20 Fibonacci numbers stored in the array         #

    la $t0, Array           # $t0 holds the memory address
                            # of the 1st array element
    move $t1, $zero         # $t1 = 0 (counter)

next:
    lw $a0, ($t0)           # load 1 element in $a0
    li $v0, 1               # syscall to print integer
    syscall                 # print it!

    
    la $a0, szComma         # load address of ", "
    li $v0, 4               # syscall to print string
    syscall                 # print it!

    addiu $t0, $t0, 4       # $t0 = address of next array element

    addiu $t1, $t1, 1       # counter++
    slti $at, $t1, 20
    bne $at, $zero, next    # If not past the end of Array, repeat

# ---------------------------------------------------------------- #

Please let me know of any suggestions or bugs regarding the code above.

Regards,

Antonis

Wednesday, March 18, 2020

MIPS jalr instruction demo

This is a sample MIPS assembler demo code to test the jalr instruction. Both the full jalr instruction syntax and the implied jalr syntax are demonstrated. The code is fully commented.

Launch EzMIPS, copy the following MIPS code and paste it into EzMIPS, the MIPS assembler editor & simulator. Assemble, Run.

# ----- Demonstration of the MIPS jalr instruction ----- #
.text

main:

# ...................................................... #
#   jalr $d, $s: rd <- return address, PC <- rs          #

    la $v0, sub1
    jalr $t0, $v0   # jump to address pointed to by $v0
                    # $t0 <- return address
                     
# ...................................................... #
# jalr $s: rd = $ra (implied)<- return address, PC <- rs #

    la $v1, sub2
    jalr $v1        # jump to address pointed to by $v1
                    # $ra(implied) <- return address

# ...................................................... #

    li $v0, 10
    syscall         # exit application

# ...................................................... #

sub1:
   sll $0, $0, 0    # Do nothing!
   jr $t0           # return to address pointed to by $t0

# ...................................................... #

sub2:
    sll $0, $0, 0   # Do nothing!
    jr $ra          # return to address pointed to by $ra

# ------------------------------------------------------ #

Please let me know of any suggestions or bugs regarding the code above.

Regards,

Antonis

EzMIPS new instructions test sample code

This is a sample MIPS assembler code to test the new instructions supported by EzMIPS v0.9.0.8. Although every care has been taken for the correct operation for all of them, I encourage you to test them thourougly and give me any feedback you feel appropriate. The new instructions are: jalr, lh, lhu, lwl, lwr, movn, movz, mthi, mtlo, sh, swl, swr, sync. The code is fully commented.

Launch EzMIPS, copy the following MIPS code and paste it into EzMIPS, the MIPS assembler editor & simulator. Assemble, Run.

# ---------------------------------------------------------------- #
# test program for the new instructions supported by EzMIPS v0.9.0.8  #
# ---------------------------------------------------------------- #
# New instructions:
# jalr, lh, lhu, lwl, lwr, movn, movz, mthi, mtlo, sh, swl, swr, sync #

.data

var_half0001: .half 0xf345
var_half0002: .half 0x0000
var_word0003: .word 0xdeadbeef
var_word0004: .word 0x11223344
var_word0005: .word 0x55667788

var_asciiz06: .asciiz "Hello "
var_asciiz07: .asciiz "there!\n"

# ---------------------------------------------------------------- #

.text
# ................................................................ #

main:

    # initialize some registers for later use #
    li $3, 100
    li $5, 10
    la $7, var_half0001
    la $27, var_word0003

# ................................................................ #
    
    la $t0, sub1          # load address of sub1()
    jalr $t0              # $ra implied ie jalr $ra, $t0
                          # ie return address is kept in $ra

    la $t0, sub2          # load address of sub2()
    jalr $t1, $t0         # return address is kept in $t1

# ................................................................ #
    
    #addiu $7, $7, 1
    lh $5, 0($7)          # check for align on halfword boundary; NICE
    lhu $6, 0($7)         # check for align on halfword boundary; NICE

# ................................................................ #

    li $10, 0xffffffff
    li $11, 0xffffffff
    li $12, 0xffffffff
    li $13, 0xffffffff
    li $14, 0x00000000
    li $15, 0x12121212

# ................................................................ #

    lwl $10, 0($27)
    lwl $11, 1($27)
    lwl $12, 2($27)
    lwl $13, 3($27)
    lwl $14, 4($27)
    lwl $15, 5($27)

# ................................................................ #

    lwr $16, 0($27)
    lwr $17, 1($27)
    lwr $18, 2($27)
    lwr $19, 3($27)
    lwr $20, 4($27)
    lwr $21, 5($27)

# ................................................................ #

    movn $6, $5, $3
    movz $7, $5, $3

# ................................................................ #

    mthi $3
    mtlo $5

# ................................................................ #

    sh $21, 2($7)
    #sh $22, 2($17)
    #sh $1, 4($27)
    #sh $2, 8($4)

# ................................................................ #
   
    swl $22, 0($27)
    swl $22, 1($27)
    swl $22, 2($27)
    swl $22, 3($27)
    swl $13, 4($27)
    swl $13, 5($27)
    swl $13, 6($27)
    swl $13, 7($27)

    addi $27, $27, 8
    swl $15, 0($27)
    swl $15, 1($27)
    swl $15, 2($27)
    swl $15, 3($27)

 # ............................................................... #
    addi $27, $27, -8
   
    swr $22, 0($27)
    swr $22, 1($27)
    swr $22, 2($27)
    swr $22, 3($27)
    swr $13, 4($27)
    swr $13, 5($27)
    swr $13, 6($27)
    swr $13, 7($27)

    addi $27, $27, 8
    swr $15, 0($27)
    swr $15, 1($27)
    swr $15, 2($27)
    swr $15, 3($27)

# ................................................................ #

    #sync

# ................................................................ #

    li $v0, 10                # return to OS
    syscall

# ................................................................ #

sub1:

    la $a0, var_asciiz06
    li $v0, 4
    syscall
    jr $ra                    # return address is in $ra

# ................................................................ #

sub2:
    
    la $a0, var_asciiz07
    li $v0, 4
    syscall
    jr $t1                    # return address is in $t1

# ................................................................ #


Please let me know of any suggestions or bugs regarding the code above.

Regards,

Antonis