11
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

アセンブリ言語(MIPS)でソート

Last updated at Posted at 2014-05-03

大学の課題用 (再 履 修)
メモリ解放の仕方が分からなかったので確保したスペース放置してる

ss (2014-05-03 at 10.35.37).png

こんな感じで SPIM コンソール上で動いてくれます

.data セクション

文字列の定義

bracket_start: .asciiz "["
bracket_end: .asciiz "]: "
input_message_0: .asciiz "Number of integers: "
input_message_1: .asciiz "Input"
output_message_0: .asciiz "Sorted results: "
output_message_1: .asciiz "Output"
error_message: .asciiz "Number of integers must be positive"
eol: .asciiz "\n"

固定的に使うレジスタの定義

  • $s0
    → 配列
  • $s1
    → 配列のサイズ

.text セクション

main ルーチン

「入力」→「ソート」→「出力」を繰り返す

バブルソート用の実装
main:

	jal read
	jal sort
	jal print
	j main
クイックソート用の実装
main:

	jal read

	# sort(0, N - 1);
	move $a0, $zero
	move $a1, $s1
	addi $a1, $a1, -1
	jal sort

	jal print
	j main

read ルーチン

ユーザー入力を受け付けて配列 $s0 に格納する

read:
	
	# "Number of integers:" と表示する
	li $v0, 4
	la $a0, input_message_0
	syscall
	
	# 生成する配列のサイズを$v0に受け取る
	li $v0, 5
	syscall
	
	# 正の数であればread_prepareにジャンプする
	bgt $v0, $zero, read_prepare
	
	# "Number of integers must be positive\n" と表示する
	li $v0, 4
	la $a0, error_message
	syscall
	la $a0, eol
	syscall
	
	# リトライさせる
	j read
	
	read_prepare:
	
	# 生成する配列のサイズを$s1に保存する
	move $s1, $v0
	
	# 配列を生成して先頭アドレスを$v0に受け取る
	sll $a0, $v0, 2
	li $v0, 9
	syscall
	
	# 生成した配列の先頭アドレスを$s0に保存する
	move $s0, $v0
	
	# 配列のオフセット用レジスタとして$t0を初期化する
	move $t0, $zero
	
	read_loop:
	
	# "Input[{$t0}]:" と表示する
	li $v0, 4
	la $a0, input_message_1
	syscall
	la $a0, bracket_start
	syscall
	li $v0, 1
	move $a0, $t0
	syscall
	li $v0, 4
	la $a0, bracket_end
	syscall
	
	# 設定する配列要素の値を$v0に受け取る
	li $v0, 5
	syscall
	
	# 実際に保存する
	sll $t1, $t0, 2
	add $t1, $t1, $s0
	sw $v0, 0($t1)
	
	# オフセットをインクリメントする
	addi $t0, $t0, 1
	
	# 作成した配列にまだ空きがあればread_loopにジャンプする
	bne $t0, $s1, read_loop
	
	# "\n" と表示する
	li $v0, 4
	la $a0, eol
	syscall
	
	# 復帰する
	jr $ra

print ルーチン

配列 $s0 の値を出力する

print:
	
	# 配列のオフセット用レジスタとして$t0を初期化する
	move $t0, $zero
	
	# "Sorting results:" と表示する
	li $v0, 4
	la $a0, output_message_0
	syscall
	la $a0, eol
	syscall
	
	print_loop:
	
	# "Output[{$t0}]:" と表示する
	li $v0, 4
	la $a0, output_message_1
	syscall
	la $a0, bracket_start
	syscall
	li $v0, 1
	move $a0, $t0
	syscall
	li $v0, 4
	la $a0, bracket_end
	syscall
	
	# 格納されている値を取り出して表示する
	sll $t1, $t0, 2
	add $t1, $t1, $s0
	li $v0, 1
	lw $a0, 0($t1)
	syscall
	
	# "\n" と表示する
	li $v0, 4
	la $a0, eol
	syscall
	
	# オフセットをインクリメントさせる
	addi $t0, $t0, 1
	
	# 配列要素の巡回がまだ済んでいなければprint_loopにジャンプする
	bne $t0, $s1, print_loop
	
	# "\n" と表示する
	li $v0, 4
	la $a0, eol
	syscall
	
	# 復帰する
	jr $ra

sort ルーチン

バブルソート用の実装
sort:
	
	# i = 0;
	move $s2, $zero;
	
	# while (i < N) {
	loop_i_start:
	bge $s2, $s1, loop_i_end
	
	# j = N - 1;
	add $s3, $s1, -1
	
	# while (j > i) {
	loop_j_start:
	ble $s3, $s2, loop_j_end
	
	# if (x[j] < x[j - 1]) swap(&x[j], &x[j - 1]);
	add $t1, $s3, -1
	sll $t0, $s3, 2
	sll $t1, $t1, 2
	add $t0, $t0, $s0
	add $t1, $t1, $s0
	lw $t2, 0($t0)
	lw $t3, 0($t1)
	bge $t2, $t3, skip_swap
	sw $t2, 0($t1)
	sw $t3, 0($t0)
	skip_swap:
	
	# --j;
	addi $s3, $s3, -1
	
	# }
	j loop_j_start
	loop_j_end:
	
	# ++i;
	addi $s2, $s2, 1
	
	# }
	j loop_i_start
	loop_i_end:
	
	# return;
	jr $ra
クイックソート用の実装
sort:
	
	# スタックへの退避
	addi $sp, $sp, -20
	sw $ra, 16($sp)
	sw $s5, 12($sp)
	sw $s4, 8($sp)
	sw $s3, 4($sp)
	sw $s2, 0($sp)
	move $s2, $a0
	move $s3, $a1
	
	# i = left;
	move $s4, $s2
	
	# j = right;
	move $s5, $s3
	
	# pivot = x[(left + right) / 2];
	add $t0, $s2, $s3
	li $t1, 2 
	div $t0, $t1
	mflo $t0
	sll $t0, $t0, 2
	add $t0, $t0, $s0
	lw $t0, 0($t0)
	
	# while (1) {
	loop_start:
	
	# while (x[i] < pivot) ++i;
	loop_i_start:
	move $t1, $s4
	sll $t1, $t1, 2
	add $t1, $t1, $s0
	lw $t1, 0($t1)
	bge $t1, $t0, loop_i_end
	addi $s4, $s4, 1

	# }
	j loop_i_start
	loop_i_end:
	
	# while (pivot < x[j]) --j;
	loop_j_start:
	move $t1, $s5
	sll $t1, $t1, 2
	add $t1, $t1, $s0
	lw $t1, 0($t1)
	bge $t0, $t1, loop_j_end
	addi $s5, $s5, -1

	# }
	j loop_j_start
	loop_j_end:
	
	# if (i >= j) break;
	bge $s4, $s5, loop_end
	
	# swap(&x[i], &x[j]);
	move $t1, $s4
	move $t2, $s5
	sll $t1, $t1, 2
	sll $t2, $t2, 2
	add $t1, $t1, $s0
	add $t2, $t2, $s0
	lw $t3, 0($t1)
	lw $t4, 0($t2)
	sw $t3, 0($t2)
	sw $t4, 0($t1)
	
	# ++i
	addi $s4, $s4, 1
	
	# --j
	addi $s5, $s5, -1
	
	# }
	j loop_start;
	loop_end:
	
	# if (left < i - 1) sort(left, i - 1);
	move $t0, $s4
	addi $t0, $t0, -1
	bge $s2, $t0, skip_left_sort
	move $a0, $s2
	move $a1, $t0
	jal sort
	skip_left_sort:
	
	# if (j + 1 < right) sort(j + 1, right);
	move $t0, $s5
	addi $t0, $t0, 1
	bge $t0, $s3, skip_right_sort
	move $a0, $t0
	move $a1, $s3
	jal sort
	skip_right_sort:
	
	# スタックからの復元
	lw $s2, 0($sp)
	lw $s3, 4($sp)
	lw $s4, 8($sp)
	lw $s5, 12($sp)
	lw $ra, 16($sp)
	addi $sp, $sp, 20
	
	# return;
	jr $ra
11
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?