Friday, February 28, 2020

atoi() function in MIPS assembler

This is demonstration sample code of the atoi() function in MIPS assembler. Launch EzMIPS, copy the following MIPS code and paste it into EzMIPS. Assemble, Run.


# ------------------ atoi() function in MIPS ----------------- #

.data

szGoodNum:   .asciiz "123"
szBadNum:    .asciiz "12a"
szError:     .ascii  "This string does not represent "
             .asciiz "a decimal integer\n"
szIntegerIs: .asciiz "- The integer number is: "


# -------------------- code section -------------------------- #
.text

    la $s1, szGoodNum      # save string address into $s1
                           # change this to szBadNum to test
    li $t0, 10
    li $t2, 48             # 48 = '0'
    li $t3, 57             # 57 = '9'

# ........................... atoi() ......................... #
atoi:
    lbu $t1, ($s1)         # load unsigned char from string
    
    beq $t1, $zero, print  # is it a NULL terminator?
    blt $t1, $t2, err      # is it < '0' ?
    bgt $t1, $t3, err      # is it > '9' ?

    addi $t1, $t1, -48     # convert $t1's ascii value to decimal
    mul $s2, $s2, $t0      # int_val *= 10
    add $s2, $s2, $t1      # int_val += array[s1] - '0'
    addi $s1, $s1, 1       # $s1 is next char's address
    j atoi                 # go get next char
    
# ....................... print error ........................ #
err:

    la $a0, szError        # address of szError string
    li $v0, 4              # print string
    syscall
    j end

# ....................... print integer ...................... #
print:

    la $a0, szIntegerIs    # address of szIntegerIs string
    li $v0, 4              # print string
    syscall
    
    move $a0, $s2
    li $v0, 1              # print integer
    syscall

# ......................... end .............................. #
end:

    li $v0, 10
    syscall

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


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

Regards,

Antonis

Thursday, February 27, 2020

MIPS jal and jr instructions

This is demonstration sample code of jal and jr MIPS instructions. Launch EzMIPS, copy the following MIPS code and paste it into EzMIPS. Assemble, Run.

# -------- demonstration of jal and jr instructions -------- #

.data
szMessage: .ascii  "- Hello world!\n- Are you ok?\n"
           .asciiz "- Yes\n- Oh, my God!\n"

.text


# ---------------------------------------------------------- #
main: 
    
    jal print           # save pc in $ra & jump to print
    jal delay           # save pc in $ra & jump to delay
    
# ---------------------------------------------------------- #
    
    li $v0, 10
    syscall             #exit the program gracefully
    
# ---------------------------------------------------------- #
print:
    
    la $a0, szMessage
    li $v0, 4
    syscall             # print string
    jr $ra              # return to caller

# ---------------------------------------------------------- #
delay:
    
    sll $zero, $zero, 0
    sll $zero, $zero, 0
    sll $zero, $zero, 0
    jr $ra              # return to caller

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


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

Regards,

Antonis

Wednesday, February 26, 2020

Store array index in all array locations, print

This sample MIPS source code will store the array index in all array locations [0..99] and print. Launch EzMIPS, copy the following MIPS code and paste it into EzMIPS. Assemble, Run.


# --- store in every array location its array index --- #

.data

szarray: .asciiz "array["
szequal: .asciiz "] = "
szLF:    .asciiz "\n"

.text

# ----------------------------------------------------- #
main:
    
    add $t0, $zero, $zero  # t0 used as a counter (i = 0)
    move $t1, $gp          # t1 = the address of the first
                           # element ($gp = 0x10008000)
    addi $t2, $0, 100      # t2 = 100
    
# ----------------------------------------------------- #
start:
    
    slt $t3, $t0, $t2      # if ($to < $t2) -> $t3 = 1
                           # otherwise $t3 = 0 

    beq $t3, $zero, print   # is $t3 = 0 -> done!

    sw $t0, 0($t1)         # a[i] = i, ie a[0] = 0, a[1] = 1 ...
    addi $t0, $t0, 1       # i = i + 1
    addi $t1, $t1, 4       # next address = address + 4
                           # (this is array of words)
    j start                # continue

# ----------------------- Print ----------------------- #

print:

    add $t0, $zero, $zero  # t0 used as a counter (i = 0)
    move $t1, $gp          # t1 = the address of the first
                           # element ($gp = 0x10008000)
    addi $t2, $0, 100      # t2 = 100
    

# ..................................................... #
next:
    slt $t3, $t0, $t2      # if ($to < $t2) -> $t3 = 1
                           # otherwise $t3 = 0 
    beq $t3, $zero, done   # is $t3 = 0 -> done!

    # print "array["
    li $v0, 4
    la $a0, szarray
    syscall

    # print integer index
    li $v0, 1
    move $a0, $t0
    syscall

    # print "] = "
    li $v0, 4
    la $a0, szequal
    syscall

    # read value from memory and print
    li $v0, 1
    lw $a0, 0($t1)
    syscall

    # print newline
    li $v0, 4
    la $a0, szLF
    syscall
# ..................................................... #

    addi $t0, $t0, 1       # i = i + 1
    addi $t1, $t1, 4       # next address = address + 4
                           # (this is an array of words)
    j next

# --------------------- exit program ------------------ #
done:
    li $v0, 10
    syscall

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

Regards,

Antonis

Monday, February 24, 2020

Open, read, print, close file in MIPS

This is Open, read, print, close file example v2. Launch EzMIPS, copy the following MIPS code and paste it into EzMIPS. Assemble, Run.

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

.data

filename:       .asciiz "test.txt"  #file name
szfilenotfound: .asciiz "'Error. File not found'"
textSpace:      .space 1050         #space to store string

.text

main:

# ----------------------- open the file --------------------- #

    li $v0, 13                # open a file
    li $a1, 0                 # file flag (read)
    la $a0, filename          # load file name
    add $a2, $zero, $zero     # file mode (unused)
    syscall
    
    bne $v0, $zero, readfile
    
    la $a0, szfilenotfound    # address of error message
    li $v0, 4                 # print string
    syscall  
    j end

# ---------------- read file text and put it in buffer ------ #

readfile:

    move $a0, $v0             # load file descriptor
    move $a3, $v0             # file descriptor for later use!
    li $v0, 14                # read from file
    la $a1, textSpace         # adrress of buffer
    li $a2, 1050              # number of bytes to be read
    syscall

# ------------- print file text already in buffer ----------- #

    la $a0, textSpace         # address of string to be printed
    li $v0, 4                 # print string
    syscall

# --------------------- close the file ---------------------- #

    move $a0, $a3             # $a3 kept the file descriptor
    li $v0, 16
    syscall

# ---------------------- exit program ------------------------ #
end:

    li $v0, 10
    syscall


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

Regards,

Antonis

strcat() implementation in MIPS

Launch EzMIPS, copy the following MIPS code and paste it into EzMIPS. Assemble, Run.

# --------- Implementation of strcat() in MIPS ---------- #

# call strcat() twice:
# 1. append var_source1 to var_target
# 2. append var_source2 to the result above
# 3. print the end result

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

.data

var_target:  .ascii  "My name is "
             .space  20
var_source1: .asciiz "Antonis "
var_source2: .asciiz "Kyprianou"

var_message: .asciiz "The final concatenated string is: " 

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

.text

# ------ load source and target string addresses -------- #

    la $a1, var_target
    la $a0, var_source1
    jal strcat                    # call strcat() function

# ------ load source and target string addresses -------- #

    la $a1, var_target
    la $a0, var_source2
    jal strcat                    # call strcat() function

# ------------------------ print message ---------------- #

    la $a0, var_message           # address of string to be
                                  # printed
    li $v0, 4                     # print string
    syscall

# ----------------- print concatenated string ----------- #

    la $a0, var_target            # address of string to be
                                  # printed
    li $v0, 4                     # print string
    syscall

# --------------------- exit program -------------------- #

    li $v0,10
    syscall

# ---------------------- strcat() ----------------------- #

strcat:                           # loop until end of
                                  # target found
    lb $t1, 0($a1)
    beq $t1, $zero, append        # is this a '\0' ?
    addi $a1, $a1, 1
    j strcat

append:
    lb $t1, 0($a0)                # read char from source
    sb $t1, 0($a1)                # append the char to the
                                  # target

    addi $a0, $a0, 1
    addi $a1, $a1, 1
    bne $t1, $zero, append        # is this a '\0' ?

return:
    jr $ra                        # yes, it is a '\0',
                                  # return to the caller
# ------------------------------------------------------- #

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

Regards,

Antonis

Sunday, February 23, 2020

strcpy() implementation in MIPS

Launch EzMIPS, copy the following MIPS code and paste it into EzMIPS. Assemble, Run.

# -------------- strcpy() implementation in MIPS ------------- #

.data


str_source:  .asciiz "Hello There!\n"

str_target:  .space 20

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


.text


# ----------- load source and target string addresses -------- #


    la $a1, str_source

    la $a0, str_target
    jal strcpy                   # call strcpy function

# ---------------------------- print ------------------------- #


    la $a0, str_target           # address of string

    li $v0, 4                    # print string
    syscall

# -------------------------- exit program -------------------- #


    li $v0, 10

    syscall

# ---------------------------- strcpy() ---------------------- #


strcpy:

    lb $t1, 0($a1)
    sb $t1, 0($a0)
    beq $t1, $zero, return
    addi $a0, $a0, 1
    addi $a1, $a1, 1
    j strcpy

return:
    jr $ra

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


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

Regards,

Antonis

Thursday, February 20, 2020

Reverse values in an array by using the stack

Launch EzMIPS, copy the following MIPS code and paste it into EzMIPS. Assemble, Run.

# Example to reverse values in an array by using the stack     #
# ------------------------------------------------------------ #

# -------------------- Data Declarations --------------------- #
.data
array: .word  1,  3,  5,  7,  9, 11, 13, 15, 17, 19
       .word 21, 23, 25, 27, 29, 31, 33, 35, 37, 39
       .word 41, 43, 45, 47, 49, 51, 53, 55, 57, 59

length: .word 30

# ------------------- Text/Code section ---------------------- #

# Basic approach:
# - loop to push each element onto the stack
# - loop to pop each element off the stack
# Final result is all elements reversed

.text

main:
# ------------------------------------------------------------ #
    # Loop to read items from array and push to stack.
    la $t0, array                 # array starting address
    li $t1, 0                     # loop index, i=0
    lw $t2, length                # length
# ------------------------------------------------------------ #

PushLoop:
    lw $t4, ($t0)                 # get array[i]
    addiu $sp, $sp, -4            # push array[i]
    sw $t4, ($sp)
    
    addi $t1, $t1, 1              # i = i+1
    addi $t0, $t0, 4              # update array address
    
    blt $t1, $t2, PushLoop        # if i<length -> continue
# ------------------------------------------------------------ #
    # Loop to pop items from stack and write into array.
    la $t0, array                 # array starting address
    li $t1, 0                     # loop index, i=0
    
    lw $t2, length                # length (redundant line)
# ------------------------------------------------------------ #

PopLoop:
    lw $t4, ($sp)
    addiu $sp, $sp, 4             # pop array[i]
    sw $t4, ($t0)                 # set array[i]
    
    addi $t1, $t1, 1              # i = i+1
    addi $t0, $t0, 4              # update array address
    
    blt $t1, $t2, PopLoop         # if i<length, continue
# ------------------------------------------------------------ #
    # Done, terminate program.
    li $v0, 10                    # terminate
    syscall                       # system call

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

Regards,

Antonis

Wednesday, February 19, 2020

Store values in memory, sort, print in MIPS

This sample MIPS source code will store predefined word values in memory, sort and print them in ascending order. Launch EzMIPS, copy the following MIPS code and paste it into EzMIPS. Assemble, Run.


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

.data
szmemoryat: .asciiz "Memory @ "
szLF:       .asciiz "\n"
szTab:      .asciiz ":\t"

.text

# ------------------------------------------------ #
main:

    ori $s0, $zero, 0x1
    sw $s0, 0($gp)
    
    ori $s0, $zero, 0x100
    sw $s0, 4($gp)
    
    ori $s0, $zero, 0x2
    sw $s0, 8($gp)
    
    ori $s0, $zero, 0x1000
    sw $s0, 12($gp)
    
    ori $s0, $zero, 0x23
    sw $s0, 16($gp)
    
    ori $s0, $zero, 0x27
    sw $s0, 20($gp)
    
    ori $s0, $zero, 0x62
    sw $s0, 24($gp)
    
    ori $s0, $zero, 0x37
    sw $s0, 28($gp)
    
    ori $s0, $zero, 0x40
    sw $s0, 32($gp)
    
    ori $s0, $zero, 0x73
    sw $s0, 36($gp)
    
    ori $s0, $zero, 0x47
    sw $s0, 40($gp)
    
    ori $s0, $zero, 0x52
    sw $s0, 44($gp)
    
    ori $s0, $zero, 0x66
    sw $s0, 48($gp)
    
    ori $s0, $zero, 0x59
    sw $s0, 52($gp)
    
    ori $s0, $zero, 0x32
    sw $s0, 56($gp)
    
    ori $s0, $zero , 0x56
    sw $s0, 60($gp)
    
    ori $s0, $zero, 0x68
    sw $s0, 64($gp)
    
    ori $s0, $zero, 0x70
    sw $s0, 68($gp)
    
    ori $s0, $zero, 0x45
    sw $s0, 72($gp)
    
    ori $s0, $zero, 0x81
    sw $s0, 76($gp)
    
    ori $s0, $zero, 0x74
    sw $s0, 80($gp)
    
    or $s0, $zero, $gp
    ori $s5, $zero, 0x15
    ori $s1, $zero, 0xFFFF
    sll $s1, $s1, 16
    ori $s1, $s1, 0xFFFF
    
    or $s2, $zero, $gp              #First pointer
    or $s3, $zero, $gp              #Last pointer
    
    addi $s2, $s2, -4
# ------------------------------------------------ #
outer_loop:

    addi $s2, $s2, 4
    and $s3, $s1, $s2
    
    addi $s3, $s3, 4
    and $s4, $s5, $s1
    
    
    addi $s5, $s5, -1
    addi $s4, $s4, -1
    
    beq $s5, $zero, end
# ------------------------------------------------ #
inner_loop:

    lw $t0, 0($s2)
    lw $t1, 0($s3)
    
    slt $t3, $t0, $t1
    
    beq $t3, $zero, outer_less
    
    addi $s3, $s3, 0x4
    addi $s4, $s4, -1
    
    beq $s4, $zero, outer_loop
    
    beq $zero, $zero, inner_loop
# ------------------------------------------------ #
outer_less:

    sw $t1, 0($s2)
    sw $t0, 0($s3)
    
    addi $s3, $s3, 0x4
    addi $s4, $s4, -1
    
    beq $s4, $zero, outer_loop
    
    beq $zero, $zero, inner_loop

end:
# ------------------- Print --------------------- #
    # Print all memory locations
    li $a3, 0
    add $a1, $gp, $a3
    li $s0, 80
    
    next_location:
    # Print "Memory @ "
    li $v0, 4
    la $a0, szmemoryat
    syscall
    
    # Print Memory location in Hex
    li $v0, 34
    move $a0, $a1
    syscall
    
    # Print tab
    li $v0, 4
    la $a0, szTab
    syscall
    
    # Load integer in memory and print it in decimal
    li $v0, 1
    lw $a0, ($a1)
    syscall
    
    # Print newline
    li $v0, 4
    la $a0, szLF
    syscall
    
    addi $a3, $a3, 4
    add $a1, $gp, $a3
    ble $a3, $s0, next_location
# ------------------------------------------------ #

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

Regards,

Antonis

Saturday, February 15, 2020

Open, write, close file in MIPS

Launch EzMIPS, copy the following MIPS code and paste it into EzMIPS. Assemble, Run.

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

.data
str_exit:  .asciiz "write_file_test.txt"
str_data:  .ascii "This is a test!\nSecond line\n"
str_data_end:

# ------------------------------------------------------- #
.text

file_open:
    li $v0, 13
    la $a0, str_exit
    li $a1, 1
    li $a2, 0
    syscall            # File descriptor is returned in $v0

file_write:
    move $a0, $v0      # Syscall 15 (file descriptor in $a0)
    li $v0, 15
    la $a1, str_data
    la $a2, str_data_end
    la $a3, str_data
    subu $a2, $a2, $a3 # computes the length of the string
    syscall

file_close:
    li $v0, 16         # $a0 already has the file descriptor
    syscall

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

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

Regards,

Antonis