Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

MIPS_primery_zadach / dandamudi05gtr guide risc processors programmers engineers

.pdf
Скачиваний:
81
Добавлен:
11.05.2015
Размер:
1.39 Mб
Скачать

256

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:

Соседние файлы в папке MIPS_primery_zadach