MIPS_primery_zadach / dandamudi05gtr guide risc processors programmers engineers
.pdf256 |
Guide to RISC Processors |
end for
if (position =min_position) then
array[min_position] := array[position] array[position] := min_value
end if end for
end selection_sort
The selection sort procedure, shown in Program 14.2, implements this pseudocode. The code on lines 80 and 81 converts the array size into bytes. The addu instruction on line 82 adds the array pointer in $a0 to this byte count to get the array-end pointer.
The first if statement is implemented on lines 92 and 93. The body of this if statement is on lines 96 and 97. The inner for loop condition is tested on line 102. The inner for loop body consists of lines 91–102.
The second if statement condition is tested on line 105. This if statement’s body is implemented on lines 108–110. The outer for loop condition is tested on line 115. The outer for loop consists of lines 86–115.
Example 14.2 Linear search of an integer array.
In this example, the user is asked to input an array of nonzero integers and then queries whether a given number is in the array. The program uses a procedure that implements the linear search to locate a given number in an unsorted array.
The program listing is given in Program 14.3. The main program is very similar to the one in the last example. Before calling the linear search procedure, it passes the array pointer (in $a0), its size (in $a1), and the number to be searched (in $a2).
The linear search procedure returns the status of the search (found or not-found) in $v0. If found, the position of the number in the array is returned in $v1. The main program outputs the appropriate message depending on the status returned by the linear search procedure.
Program 14.3 Linear search of an array
1: # Linear search |
LINEAR_SEARCH.ASM |
2:#
3:# Objective: Searches for an integer using linear search.
4:# Input: Requests array input and the number
5: # |
to be searched; |
6:# Output: Outputs the position of the number, if found.
7:#
8:# $a0 - array pointer
9:# $a1 - array size
10:# $a2 - number to be searched
Chapter 14 • Conditional Execution |
257 |
11:#
12:#################### Data segment ########################
13:.data
14:array_prompt:
15: |
.ascii |
"Please enter integers.\n" |
16: |
.asciiz |
"Entering zero terminates the input.\n" |
17:number_prompt:
18: |
.asciiz |
"Enter the number to be searched:\n" |
19:found_msg:
20: |
.asciiz |
"The number is at position\n" |
21:not_found_msg:
22: |
.asciiz |
"The number is not in the array!\n" |
23:newline:
24:.asciiz "\n"
25:.align 2
26:array:
27: |
.space |
200 |
# space for 50 integers |
28: |
|
|
|
29:#################### Code segment ########################
30:.text
31:.globl main
32:main:
33: |
la |
$a0,array_prompt # prompt user for input |
34:li $v0,4
35:syscall
37:la $t0,array
38:read_more:
39: |
li |
$v0,5 |
# read a number |
40:syscall
41: |
sw |
$v0,($t0) |
# store it in the array |
42:beqz $v0,exit_read
43:addu $t0,$t0,4
44: b read_more
45:exit_read:
46: |
la |
$a0,number_prompt # prompt user for number |
47:li $v0,4
48:syscall
49: |
li |
$v0,5 |
# |
read a number |
50: |
syscall |
# |
number in $v0 |
|
51: |
|
|
|
|
52:# prepare arguments for procedure call
53: |
la |
$a0,array |
# $a0 = array pointer |
54:subu $a1,$t0,$a0 # $a1 = array size in bytes
55: |
srl |
$a1,$a1,2 |
# |
$a1 |
= |
$a1/4 |
56: |
move |
$a2,$v0 |
# |
$a2 |
= |
given number |
57: |
jal |
lin_search |
|
|
|
|
258 |
Guide to RISC Processors |
58:
59:beqz $v0,not_found
60: |
la |
$a0,found_msg |
# write found message |
61:li $v0,4
62:syscall
63: |
move $a0,$v1 |
# write position |
64:li $v0,1
65:syscall
66: |
la |
$a0,newline |
# write newline |
67:li $v0,4
68:syscall
69: |
b |
done |
70: |
|
|
71:not_found:
72: |
la |
$a0,not_found_msg # write not found message |
73:li $v0,4
74:syscall
75:done:
76: |
li |
$v0,10 |
# exit |
77: |
syscall |
|
|
78: |
|
|
|
79:#-------------------------------------------------------
80:# LIN_SEARCH receives a pointer to the array in $a0,
81:# its size in $a1, and the number to be searched in $a2.
82:# It uses linear search algorithm.
83:# $t0 - array pointer
84:# $t1 - array value
85:# $a1 - pointer to the last element
86:# $v0 - status (0 = not found, 1 = found)
87:# $v1 - position if found
88:#-------------------------------------------------------
89:lin_search:
90:# computes the address of the last element
91:subu $a1,$a1,1
92:sll $a1,$a1,2
93:addu $a1,$a1,$a0
95:move $t0,$a0
96:loop:
#last element index
#convert to bytes ($a1 * 4)
#$a1 = pointer to last element
#$t0 = array pointer
97: |
lw |
$t1,($t0) |
# array value in $t1 |
98:beq $t1,$a2,num_found
99:addu $t0,$t0,4 # point to the next element
100:bleu $t0,$a1,loop
101:
102:# number not found
103: |
li |
$v0,0 |
# status = not found |
104: |
b |
search_done |
|
Chapter 14 • Conditional Execution |
259 |
105:
106:num_found:
107: |
li |
$v0,1 |
# status = found |
108:# compute the position
109:subu $v1,$t0,$a0
110:srl $v1,$v1,2
111:addu $v1,$v1,1
112:search_done:
113: jr $ra
The linear search procedure receives a pointer to the array, its size, and the number to be searched. The search process starts at the first element of the array and proceeds until either the element is located or the array is exhausted. First we have to convert the array size into number of bytes (lines 91 and 92). As in the selection sort procedure, we use sll to multiply the size by 4 (line 92). To compute the address of the last element, we add the array pointer to this byte count (line 93).
The search loop consists of lines 96–100. The loop iteration condition is tested on line 100 and the comparison to the number is done on line 98. If the number is not found in the array, the $v0 is cleared to zero (line 103) to indicate the not-found status. On the other hand, if the number is found, $v0 is set to 1 (line 107). In this case, we have to compute the position of the number in the array, which is done on lines 109–111. We use the srl instruction on line 110 to divide the byte count by 4.
Indirect Jumps
So far, we have used only the direct jump instructions. We now look at indirect jumps. In an indirect jump, the target address is specified indirectly. The MIPS architecture provides a register-based indirect jump instruction. As we have seen before, the format of this instruction is
jr rs
where rs is a register. We have already discussed this instruction in Chapter 11 (see page 188). The next example shows how indirect jumps can be used with a jump table stored in memory.
Example 14.3 An example with an indirect jump.
The objective here is to show how we can use the indirect jump instruction. To this end, we show a simple program that reads a digit from the user and prints the corresponding choice represented by the input. The listing is shown in Program 14.4. An input between 0 and 9 is valid. If a nondigit input is given to the program, it displays an error message and requests a valid digit input. If the input is 0, 1, or 2, it displays a simple message to indicate the class selection. Other digits terminate the program.
260 |
|
Guide to RISC Processors |
|
Program 14.4 A simple program to illustrate indirect jumps |
|
1: |
# Indirect jump program |
INDIRECT_JUMP.ASM |
2:#
3:# Objective: To demonstrate indirect jumps.
4:# Input: Requests a digit.
5:# Output: Outputs the class selected.
6:#
7:################### Data segment ###################
8:.data
9:prompt:
10: |
.asciiz |
"Please enter a digit: " |
11:try_prompt:
12: |
.asciiz |
"Not a digit! Try again: \n" |
13:msg0:
14: |
.asciiz |
"Economy class selected.\n" |
15:msg1:
16: |
.asciiz |
"Business class selected.\n" |
17:msg2:
18: |
.asciiz |
"First class selected.\n" |
19:default_msg:
20: |
.asciiz |
"Not a valid selection!\n" |
21:newline:
22: |
.asciiz |
"\n" |
23: |
|
|
24:input_digit:
25: |
.space |
2 |
26: |
|
|
27:jump_table:
28: |
.word |
code_for_0 |
29: |
.word |
code_for_1 |
30: |
.word |
code_for_2 |
31: |
.word |
default_code |
32: |
.word |
default_code |
33: |
.word |
default_code |
34: |
.word |
default_code |
35: |
.word |
default_code |
36: |
.word |
default_code |
37: |
.word |
default_code |
38: |
|
|
39:################### Code segment ###################
40:.text
41:.globl main
42:main:
43: |
la |
$a0,prompt |
# prompt user for input |
44:li $v0,4
45:syscall
Chapter 14 • |
Conditional Execution |
261 |
|
46: |
|
|
|
47: |
la |
$a0,input_digit |
# read input |
48:li $a1,2
49:li $v0,8
50:syscall
51:la $a0,newline
52:li $v0,4
53:syscall
54:
55:lbu $t0,input_digit
56: |
sub |
$t0,$t0,’0’ |
# $t0 = input - ’0’ |
57: |
bgtu |
$t0,9,not_digit |
# if >9, not a digit |
58: |
bltz |
$t0,not_digit |
# if <0, not a digit |
59: |
|
|
|
60: |
sll |
$t0,$t0,2 |
# $t0 = $t0*4 |
61: |
|
|
|
62:# we have to jump to the pointer in jump_table
63:la $t1,jump_table
64:add $t1,$t1,$t0
65:lw $t2,($t1)
66:jr $t2
67: |
|
|
|
|
68: |
not_digit: |
|
# |
input is not a digit |
69: |
la |
$a0,try_prompt |
# |
ask user to try again |
70:li $v0,4
71:syscall
72: |
b |
main |
73: |
|
|
74:code_for_0:
75: |
la |
$a0,msg0 |
# write message 0 |
76:li $v0,4
77:syscall
78: |
b |
done |
79: |
|
|
80:code_for_1:
81: |
la |
$a0,msg1 |
# write message 1 |
82:li $v0,4
83:syscall
84: |
b |
done |
85: |
|
|
86:code_for_2:
87: |
la |
$a0,msg2 |
# write message 2 |
88:li $v0,4
89:syscall
90: |
b |
done |
91: |
|
|
92:default_code:
262 |
|
|
Guide to RISC Processors |
93: |
la |
$a0,default_msg |
# write default message |
94:li $v0,4
95:syscall
97:done:
98: |
li |
$v0,10 |
# exit |
99:syscall
In order to use the indirect jump, we have to build a jump table of pointers (see lines 27–37). The input is tested for its validity on lines 56–58. If the input is a digit, it is converted to act as an index into the jump table (line 60). This value is used in the indirect jump instruction (lines 63–66). The rest of the program is straightforward to follow.
Indirect Procedures
In this section we look at indirect procedure calls. The mechanism is very similar to that used for the indirect jumps in the last example. However, we cannot use the jr instruction for procedure calls. For this purpose the MIPS architecture provides a separate jump and link instruction. The format of this instruction is similar to the jr instruction, as shown here:
jalr rs
where rs is a register. This instruction works as does the jal instruction but takes the contents of rs as the target address. The next example illustrates how we can use this instruction to effect indirect procedure calls.
Example 14.4 An example with an indirect procedure call.
The objective here is to show how we can use the jalr instruction. The main program prompts the user for a string and a digit between 0 and 3 to select an option on how the string should be processed. The available choices are:
0 — convert to uppercase
1 — convert to lowercase
2 — flip the case
3 — reverse the string
These four functions are implemented as procedures, as shown in Program 14.5. To invoke the appropriate procedure based on the user choice, we use the jalr instruction. To facilitate this, we build the jump table as in the last example (lines 26–30). Once this value is loaded into $t2, we can specify this register in the jalr instruction on line 60.
Chapter 14 • Conditional Execution |
263 |
Program 14.5 An example to illustrate indirect procedure calls |
|
1: # Indirect jump program |
INDIRECT_PROCS.ASM |
2:#
3:# Objective: To demonstrate indirect procedures.
4:# Input: Requests a string and a digit.
5:# Output: Outputs the processed string.
6:#
7:################### Data segment ###################
8:.data
9:string_prompt:
10: |
.asciiz |
"Please enter a string (<80 chars): " |
11:digit_prompt:
12: |
.ascii |
"Please enter a digit: \n" |
||
13: |
.ascii |
" |
0 |
- to convert to upper case\n" |
14: |
.ascii |
" |
1 |
- to convert to lower case\n" |
15: |
.ascii |
" |
2 |
- to flip case\n" |
16: |
.ascii |
" |
3 |
- to reverse string\n" |
17: |
.asciiz |
" |
Other numbers are invalid.\n" |
|
18:try_prompt:
19: |
.asciiz |
"Not a valid selection! Try again:\n" |
20:out_msg:
21: |
.asciiz |
"The output string is: " |
22: |
|
|
23:input_string:
24: |
.space |
82 |
25: |
|
|
26:jump_table:
27: |
.word |
to_upper_case |
28: |
.word |
to_lower_case |
29: |
.word |
to_flip_case |
30: |
.word |
string_reverse |
31: |
|
|
32:################### Code segment ###################
33:.text
34:.globl main
35:main:
36: |
la |
$a0,string_prompt # prompt for string |
37:li $v0,4
38:syscall
39: |
la |
$a0,input_string # read input |
40:li $a1,82
41:li $v0,8
42:syscall
43:
44:digit_again:
45: |
la |
$a0,digit_prompt # prompt for digit |
264 |
Guide to RISC Processors |
46:li $v0,4
47:syscall
48: |
li |
$v0,5 |
# read input |
49: |
syscall |
|
|
50: |
|
|
|
51: |
bgtu |
$v0,3,not_valid |
# if >3, not valid |
52: |
|
|
|
53: |
sll |
$v0,$v0,2 |
# $v0 = $v0*4 |
54: |
|
|
|
55:# we have to jump to the pointer in jump_table
56:la $t1,jump_table
57:add $t1,$t1,$v0
58:lw $t2,($t1)
59: |
la |
$a0,input_string |
# |
string address in $a0 |
60: |
jalr |
$t2 |
|
|
61: |
|
|
|
|
62: |
la |
$a0,out_msg |
# |
display output message |
63:li $v0,4
64:syscall
65: |
la |
$a0,input_string # display output string |
66:li $v0,4
67:syscall
68: |
b |
done |
|
69: |
|
|
|
70: |
not_valid: |
|
# input is not a digit |
71: |
la |
$a0,try_prompt |
# ask user to try again |
72:li $v0,4
73:syscall
74: |
b |
digit_again |
75: |
|
|
76:done:
77: |
li |
$v0,10 |
# exit |
78: |
syscall |
|
|
79: |
|
|
|
80:#------------------------------------------------------
81:# STRING_REVERSE receives a pointer to a string in $a0
82:# and reverses the string
83:#------------------------------------------------------
84:string_reverse:
85: |
move $t1,$a0 |
# $t1 points to string |
86:loop1:
87:lbu $t2,($t1)
88: |
beq |
$t2,0xA,done1 |
# |
if |
linefeed |
89: |
beqz |
$t2,done1 |
# |
or |
NULL, we are done |
90:addu $t1,$t1,1
91: b loop1
92:done1:
Chapter 14 • |
Conditional Execution |
265 |
93: |
sub $t1,$t1,1 |
# $t1 points to end of string |
94:reverse_loop:
95:bleu $t1,$a0,done_reverse
96:lbu $t2,($a0)
97:lbu $t3,($t1)
98:sb $t2,($t1)
99:sb $t3,($a0)
100:addu $a0,$a0,1
101:subu $t1,$t1,1
102:b reverse_loop
103:done_reverse:
104:jr $ra
105:
106:#-----------------------------------------------------
107:# TO_UPPER_CASE receives a pointer to a string in $a0
108:# and returns the string with lowercase letters
109:# replaced by uppercase letters
110:#-----------------------------------------------------
111:to_upper_case:
112:
113:upper_loop:
114:lbu $t1,($a0)
115: |
beqz $t1,done_upper |
# if NULL, we are done |
116:bgtu $t1,’z’,skip_upper
117:bltu $t1,’a’,skip_upper
118:subu $t1,$t1,0x20
119:skip_upper:
120:sb $t1,($a0)
121:addu $a0,$a0,1
122:b upper_loop
123:done_upper:
124:jr $ra
125:
126:#-----------------------------------------------------
127:# TO_LOWER_CASE receives a pointer to a string in $a0
128:# and returns the string with uppercase letters
129:# replaced by lowercase letters
130:#-----------------------------------------------------
131:to_lower_case:
132:
133:lower_loop:
134:lbu $t1,($a0)
135: |
beqz $t1,done_lower |
# if NULL, we are done |
136:bgtu $t1,’Z’,skip_lower
137:bltu $t1,’A’,skip_lower
138:addu $t1,$t1,0x20
139:skip_lower:
