简体   繁体   中英

MIPS: Accessing and comparing an element from an array of strings

For my assignment we are given an array of names and an array of integers which represent the ages of the corresponding names (this is basically a dictionary or a map). We are supposed to read in a string from the user, and if that name is in the array, then we print that persons age. Heres what I have so far:

.data
names: .asciiz "steve","john","chelsea","julia","ryan"
ages: .byte 20,25,22,21,23
out1: .asciiz "Please enter a name:"
out2: .asciiz "Age is: "
notfound: .asciiz "Not found!" 
input: .asciiz 

.text
li $v0, 4
la $a0, out1
syscall        #prompts user for name

li $v0, 8
la $a0, input
li $a1, 20
syscall        #Reads a name into address "input"

CheckNames:   #needs to compare the input string with each element of "names" array and return 1 if they match
la $t0, (names)
la $t1, (input)
beq $t1, $t0, printAge

printAge:

I realize that my CheckNames function is wrong, but I don't know how to iterate through the array of names when each name differs in size (since I can't use an offset to get to the next name)

I faced this problem today. If it still helps you (or anybody else), I overcame this issue using the fact that .asciiz data in Assembly are an especial string of characteres that terminate themselves always with a special signal: NUL. The ASCII's table below could help ilustrate this:

ASCII Table

Keeping in mind that every character fills 8 bits (1 byte) of information, you can use these knowledge to go through all the bytes in the string's array and identify the end of each world by comparing the load byte with the $0 register (or a register with data equivalent with zero).

A pseudo-code is presented below to help you construct your own code:

move $a1, $s0   # $s0 register store the normal index of the string names(1), for example
li $t0, 0
li $t2, 0   # cont to know how many word did you pass
li $t1, maxSpace   # maxSpace is that maximum space in the array
while ($t2<$t1) {
  branch to "final", if $t1 == $a1
  lb $t3, names($t0)
  branch to "isnotNUL", if $t3 != $0
  $t2 = $t2 + 1
  $t0 = $t0 + 1
  isnotNUL:
    $t0 = $t0 + 1
}
# normal part of code to print a string .asciiz passing the start adress to $a0
final:
  li $v0, 4
  la $a0, names($t0)
  syscall
  jr $ra

There is just one problem with this method: the iteration could be very slow - specially if the array is big and the strings are also big. If this is your case and you don't want that, you could modify the code to save the numbers of bytes each string of the array has and construct a LUT (Look up table) with this information. So, you would run this function on the start of the program and when the time to print the information has come, you already know the adress you shuold start by loading the initial adress of the array and adding to it the number saved on the LUT.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM