Merge pull request 'Submit HW1' (#1) from HW1 into main
Reviewed-on: #1
This commit is contained in:
7
.gitignore
vendored
7
.gitignore
vendored
@@ -1,4 +1,9 @@
|
||||
*.zip
|
||||
*.pdf
|
||||
*/attachment/
|
||||
*.docx
|
||||
*.docx
|
||||
*.out
|
||||
*.aux
|
||||
*.log
|
||||
*.synctex(busy)
|
||||
*.synctex.gz
|
||||
7
1/README.txt
Normal file
7
1/README.txt
Normal file
@@ -0,0 +1,7 @@
|
||||
汇编大作业说明文档.docx 本次作业的具体内容说明
|
||||
汇编实验指导.pdf 为MIPS重点内容复习及大作业解释
|
||||
example/ “MARS环境安装与基础使用方法”部分参考代码
|
||||
exp1/ 作业“第一部分:基础练习”参考代码和样例数据
|
||||
exp2/ 作业“第二部分:实战应用”参考代码和样例数据
|
||||
attachment/ 实验用附件
|
||||
reference/ 参考文献
|
||||
BIN
1/example/example.in
Normal file
BIN
1/example/example.in
Normal file
Binary file not shown.
BIN
1/example/example.out
Normal file
BIN
1/example/example.out
Normal file
Binary file not shown.
58
1/example/example_0.asm
Normal file
58
1/example/example_0.asm
Normal file
@@ -0,0 +1,58 @@
|
||||
.data
|
||||
in_buff: .space 512
|
||||
out_buff: .space 512
|
||||
input_file: .asciiz "example.in"
|
||||
output_file: .asciiz "example.out"
|
||||
comma: .asciiz ", "
|
||||
.text
|
||||
la $a0, input_file #input_file <EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD>
|
||||
li $a1, 0 #flag 0Ϊ<EFBFBD><EFBFBD>ȡ 1Ϊд<EFBFBD><EFBFBD>
|
||||
li $a2, 0 #mode is ignored <EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ0<EFBFBD>Ϳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
li $v0, 13 #13 Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD> syscall <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
syscall # <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɹ<EFBFBD> <EFBFBD><EFBFBD> <EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ص<EFBFBD>$v0<EFBFBD><EFBFBD>
|
||||
move $a0,$v0 # <EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>뵽 $a0<EFBFBD><EFBFBD>
|
||||
la $a1, in_buff #in_buff Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݴ<EFBFBD><EFBFBD><EFBFBD>
|
||||
li $a2, 512 #<EFBFBD><EFBFBD>ȡ512<EFBFBD><EFBFBD>byte
|
||||
li $v0, 14 #14 Ϊ<EFBFBD><EFBFBD>ȡ<EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD> syscall <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
syscall
|
||||
li $v0 16 #16 Ϊ<EFBFBD>ر<EFBFBD><EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD> syscall <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
syscall
|
||||
|
||||
#<EFBFBD><EFBFBD>ַ<EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵΪN
|
||||
la $s0, in_buff
|
||||
la $s1, out_buff
|
||||
lw $s2, 0($s0)
|
||||
li $t0, 0
|
||||
|
||||
#<EFBFBD><EFBFBD>ַ<EFBFBD><EFBFBD>4 ѭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>1
|
||||
for: addi $s0, $s0, 4
|
||||
addi $t0, $t0, 1
|
||||
lw $t1, 0($s0)
|
||||
sw $t1, 0($s1)
|
||||
addi $s1, $s1, 4
|
||||
#<EFBFBD><EFBFBD>ӡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
move $a0, $t1
|
||||
li $v0, 1
|
||||
syscall
|
||||
#<EFBFBD><EFBFBD>ӡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
la $a0, comma
|
||||
li $v0, 4
|
||||
syscall
|
||||
bne $t0 $s2 for
|
||||
|
||||
la $a0, output_file #output_file <EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD>
|
||||
li $a1, 1 #flag 0Ϊ<EFBFBD><EFBFBD>ȡ 1Ϊд<EFBFBD><EFBFBD>
|
||||
li $a2, 0 #mode is ignored <EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ0<EFBFBD>Ϳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
li $v0, 13 #13 Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD> syscall <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
syscall # <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɹ<EFBFBD> <EFBFBD><EFBFBD> <EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ص<EFBFBD>$v0<EFBFBD><EFBFBD>
|
||||
|
||||
move $a0,$v0 # <EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>뵽 $a0<EFBFBD><EFBFBD>
|
||||
la $a1, out_buff #in_buff Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݴ<EFBFBD><EFBFBD><EFBFBD>
|
||||
sll $s2 $s2 2
|
||||
move $a2, $s2 #д<EFBFBD><EFBFBD>512<EFBFBD><EFBFBD>byte
|
||||
li $v0, 15 #15 Ϊд<EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD> syscall <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
syscall
|
||||
#<EFBFBD><EFBFBD>ʱ$a0 <EFBFBD>е<EFBFBD><EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><EFBFBD>
|
||||
#ֱ<EFBFBD>ӵ<EFBFBD><EFBFBD><EFBFBD> syscall 16 <EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD>
|
||||
li $v0 16 #16 Ϊ<EFBFBD>ر<EFBFBD><EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD> syscall <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
syscall
|
||||
12
1/example/example_1.asm
Normal file
12
1/example/example_1.asm
Normal file
@@ -0,0 +1,12 @@
|
||||
.data
|
||||
.a
|
||||
string: .asciiz "Hello World!\n"
|
||||
|
||||
.text
|
||||
main:
|
||||
la $a0 string #载入字符串地址
|
||||
li $v0 4 #4代表打印字符串
|
||||
syscall #执行系统调用
|
||||
|
||||
li $v0 17 #17代表exit
|
||||
syscall #执行系统调用
|
||||
50
1/example/example_2.asm
Normal file
50
1/example/example_2.asm
Normal file
@@ -0,0 +1,50 @@
|
||||
.data
|
||||
stringz: .asciiz "Hello World!\n"
|
||||
string: .ascii "Hello World!\n"
|
||||
#让array对齐到4byte边界
|
||||
.align 4 #没有这句话可能会出错
|
||||
array: .space 512
|
||||
#以下常数数组会自动对齐到对应边界
|
||||
barray: .byte 1,2,3,4
|
||||
harray: .half 1,2,3,4
|
||||
warray: .word 1,2,3,4
|
||||
|
||||
|
||||
.text
|
||||
main:
|
||||
la $a0 stringz #载入字符串地址
|
||||
li $v0 4 #4代表打印字符串
|
||||
syscall #执行系统调用
|
||||
|
||||
la $a0 string #载入字符串地址
|
||||
li $v0 4 #4代表打印字符串
|
||||
syscall #执行系统调用
|
||||
|
||||
la $t0 barray #载入byte数组地址
|
||||
lb $a0 0($t0) #读取barray[0]
|
||||
li $v0 1 #1代表打印一个整数
|
||||
syscall #打印array[0]的数据
|
||||
lb $a0 1($t0) #读取barray[1]
|
||||
li $v0 1 #1代表打印一个整数
|
||||
syscall #打印array[0]的数据
|
||||
lb $a0 2($t0) #读取barray[2]
|
||||
li $v0 1 #1代表打印一个整数
|
||||
syscall #打印array[0]的数据
|
||||
lb $a0 3($t0) #读取barray[3]
|
||||
li $v0 1 #1代表打印一个整数
|
||||
syscall #打印array[0]的数据
|
||||
|
||||
li $a0 10 #10代表换行符'\n'
|
||||
li $v0 11 #11代表打印字符
|
||||
syscall #换个行
|
||||
|
||||
la $t0 array #载入array的地址
|
||||
li $t1 123
|
||||
sw $t1 0($t0) #在array[0]的位置存入123
|
||||
lw $a0 0($t0) #读取array[0]的数据
|
||||
li $v0 1 #1代表打印一个整数
|
||||
syscall #打印array[0]的数据
|
||||
|
||||
|
||||
li $v0 17 #17代表exit
|
||||
syscall #执行系统调用
|
||||
35
1/example/example_3.asm
Normal file
35
1/example/example_3.asm
Normal file
@@ -0,0 +1,35 @@
|
||||
.text
|
||||
main:
|
||||
li $v0 5 #5代表读入一个整数
|
||||
syscall #ִ执行系统调用
|
||||
move $a0 $v0 #将读入的整数作为第一个参数
|
||||
li $v0 5 #5代表读入一个整数
|
||||
syscall #ִ执行系统调用
|
||||
move $a1 $v0 #将读入的整数作为第二个参数
|
||||
|
||||
jal product #跳转到子过程product
|
||||
move $a0 $v0 #将返回值赋值给$a0
|
||||
li $v0 1 #1代表打印一个整数
|
||||
syscall #ִ执行系统调用
|
||||
|
||||
li $v0 17 #17代表exit
|
||||
syscall #ִ执行系统调用
|
||||
|
||||
product:
|
||||
move $t0 $a0 #将第一个参数赋值给t0作为累加值
|
||||
move $t1 $a1 #将第二个参数赋值给t1作为计数器
|
||||
move $t2 $zero#结果清零
|
||||
addi $sp $sp -16 #移动栈指针到栈顶
|
||||
sw $t0 12($sp) #存入本地变量t0
|
||||
sw $t1 8($sp) #存入本地变量t1
|
||||
sw $t2 4($sp) #存入本地变量t2
|
||||
sw $ra 0($sp) #存入过程返回地址
|
||||
loop: add $t2 $t2 $t0 #结果累计t0
|
||||
sw $t2 4($sp) #存入本地变量t2
|
||||
addi $t1 $t1 -1 #计数器减一
|
||||
sw $t1 8($sp) #存入本地变量t2
|
||||
bnez $t1 loop #如果计数器不为0循环继续
|
||||
move $v0 $t2 #将结果赋给返回值
|
||||
lw $ra 0($sp) #出栈过程返回地址
|
||||
jr $ra #跳转回上一级过程
|
||||
|
||||
BIN
1/exp1/a.in
Normal file
BIN
1/exp1/a.in
Normal file
Binary file not shown.
18
1/exp1/exp1_1.cpp
Normal file
18
1/exp1/exp1_1.cpp
Normal file
@@ -0,0 +1,18 @@
|
||||
#include "stdio.h"
|
||||
|
||||
int main() {
|
||||
FILE *infile ,*outfile;
|
||||
int i;
|
||||
int *buffer;
|
||||
buffer = new int[2];
|
||||
infile = fopen("a.in", "rb");
|
||||
fread(buffer, 4, 2, infile);
|
||||
fclose(infile);
|
||||
outfile = fopen("a.out", "wb");
|
||||
fwrite(buffer, 4, 2, outfile);
|
||||
fclose(outfile);
|
||||
scanf("%d", &i);
|
||||
i = i + 10;
|
||||
printf("%d", i);
|
||||
return 0;
|
||||
}
|
||||
12
1/exp1/exp1_2.cpp
Normal file
12
1/exp1/exp1_2.cpp
Normal file
@@ -0,0 +1,12 @@
|
||||
#include "stdio.h"
|
||||
|
||||
int main() {
|
||||
int i, j, temp;
|
||||
scanf("%d", &i);
|
||||
scanf("%d", &j);
|
||||
i = -i;
|
||||
if(j < 0) j = -j;
|
||||
for(temp = 0; temp < j; ++temp) i += 1;
|
||||
printf("%d",i);
|
||||
return 0;
|
||||
}
|
||||
15
1/exp1/exp1_3.cpp
Normal file
15
1/exp1/exp1_3.cpp
Normal file
@@ -0,0 +1,15 @@
|
||||
#include "stdio.h"
|
||||
|
||||
int main() {
|
||||
int *a, n, i, t;
|
||||
scanf("%d", &n);
|
||||
a = new int [n];
|
||||
for(i = 0; i < n; i++) scanf("%d",&a[i]);
|
||||
for(i = 0; i < n / 2; i++) {
|
||||
t = a[i] + 1;
|
||||
a[i] = a[n - i - 1] + 1;
|
||||
a[n - i - 1] = t;
|
||||
}
|
||||
for(i = 0;i < n; i++) printf("%d", a[i]);
|
||||
return 0;
|
||||
}
|
||||
18
1/exp1/exp1_4.cpp
Normal file
18
1/exp1/exp1_4.cpp
Normal file
@@ -0,0 +1,18 @@
|
||||
#include "stdio.h"
|
||||
|
||||
int Hanoi(int n)
|
||||
{
|
||||
if (n == 1) { // 基准情形
|
||||
return 1;
|
||||
} else { // 递归情形
|
||||
return 2 * Hanoi(n - 1) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
int n;
|
||||
scanf("%d", &n);
|
||||
printf("%d", Hanoi(n));
|
||||
return 0;
|
||||
}
|
||||
BIN
1/exp2/a.in
Normal file
BIN
1/exp2/a.in
Normal file
Binary file not shown.
58
1/exp2/binary_insert_sort.cpp
Normal file
58
1/exp2/binary_insert_sort.cpp
Normal file
@@ -0,0 +1,58 @@
|
||||
#include "stdio.h"
|
||||
/*
|
||||
二分插入排序:通过二分查找找到插入位置,然后将元素插入到指定位置。
|
||||
*/
|
||||
|
||||
// 统计待排序数据的比较次数
|
||||
int compare_count = 0;
|
||||
|
||||
// 递归二分查找插入位置
|
||||
int binary_search(int v[], int left, int right, int n)
|
||||
{
|
||||
if (left > right)
|
||||
return left; // 递归边界,此处不统计比较次数
|
||||
int mid = (left + right) >> 1;
|
||||
compare_count++; // 统计比较次数
|
||||
if (v[mid] > v[n])
|
||||
return binary_search(v, left, mid - 1, n);
|
||||
else
|
||||
return binary_search(v, mid + 1, right, n);
|
||||
}
|
||||
|
||||
// 将新的元素插入到指定位置,并将后续元素后移
|
||||
void insert(int *v, int k, int n)
|
||||
{
|
||||
int i;
|
||||
int tmp = v[n];
|
||||
for (i = n - 1; i >= k; i--)
|
||||
{
|
||||
v[i + 1] = v[i];
|
||||
}
|
||||
v[k] = tmp;
|
||||
}
|
||||
|
||||
void binary_insertion_sort(int v[], int n)
|
||||
{
|
||||
int i;
|
||||
for (i = 1; i < n; i++)
|
||||
{ // 从第二个元素开始,依次插入到前面已经排好序的序列中
|
||||
int place = binary_search(v, 0, i - 1, i);
|
||||
insert(v, place, i);
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
FILE *infile, *outfile;
|
||||
int buffer[1001];
|
||||
infile = fopen("a.in", "rb");
|
||||
fread(buffer, 4, 1001, infile);
|
||||
fclose(infile);
|
||||
int N = buffer[0];
|
||||
binary_insertion_sort(&(buffer[1]), N);
|
||||
buffer[0] = compare_count;
|
||||
outfile = fopen("a.out", "wb");
|
||||
fwrite(buffer, 4, N + 1, outfile);
|
||||
fclose(outfile);
|
||||
return 0;
|
||||
}
|
||||
59
1/exp2/insert_sort.cpp
Normal file
59
1/exp2/insert_sort.cpp
Normal file
@@ -0,0 +1,59 @@
|
||||
#include "stdio.h"
|
||||
/*
|
||||
插入排序:将一个元素插入到一个已经排好序的序列中,使得序列依然有序。
|
||||
*/
|
||||
|
||||
// 统计比较次数
|
||||
int compare_count = 0;
|
||||
|
||||
// 从后往前查找第一个比v[n]小的元素,其后一个位置即为插入位置
|
||||
int search(int v[], int n)
|
||||
{
|
||||
int i;
|
||||
int tmp = v[n];
|
||||
for (i = n - 1; i >= 0; i--)
|
||||
{
|
||||
compare_count++; // 统计比较次数
|
||||
if (v[i] <= tmp)
|
||||
break;
|
||||
}
|
||||
return i + 1;
|
||||
}
|
||||
|
||||
// 将新的元素插入到指定位置,并将后续元素后移
|
||||
void insert(int *v, int k, int n)
|
||||
{
|
||||
int i;
|
||||
int tmp = v[n];
|
||||
for (i = n - 1; i >= k; i--)
|
||||
{
|
||||
v[i + 1] = v[i];
|
||||
}
|
||||
v[k] = tmp;
|
||||
}
|
||||
|
||||
void insertion_sort(int v[], int n)
|
||||
{
|
||||
int i;
|
||||
for (i = 1; i < n; i++)
|
||||
{ // 从第二个元素开始,依次插入到前面已经排好序的序列中
|
||||
int place = search(v, i);
|
||||
insert(v, place, i);
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
FILE *infile, *outfile;
|
||||
int buffer[1001];
|
||||
infile = fopen("a.in", "rb");
|
||||
fread(buffer, 4, 1001, infile);
|
||||
fclose(infile);
|
||||
int N = buffer[0];
|
||||
insertion_sort(&(buffer[1]), N);
|
||||
buffer[0] = compare_count;
|
||||
outfile = fopen("a.out", "wb");
|
||||
fwrite(buffer, 4, N + 1, outfile);
|
||||
fclose(outfile);
|
||||
return 0;
|
||||
}
|
||||
121
1/exp2/merge_sort.cpp
Normal file
121
1/exp2/merge_sort.cpp
Normal file
@@ -0,0 +1,121 @@
|
||||
#include "stdio.h" /*
|
||||
|
||||
链表的归并排序的核心是将链表分成前后两段,分别排序后对两个有序链表归并,递归边界是当前链表长度为1。
|
||||
*/
|
||||
|
||||
int compare_count = 0;
|
||||
|
||||
// 两个有序链表合并 , 将右链元素插入到左链中 。
|
||||
int *merge(int *l_head, int *r_head)
|
||||
{
|
||||
// 这里构建一个虚拟头结点 , 方便在第一个元素前插入 。
|
||||
int *head = new int[2];
|
||||
head[1] = (int)l_head;
|
||||
int *p_left = head;
|
||||
int *p_right = r_head;
|
||||
do
|
||||
{
|
||||
do
|
||||
{ // 寻找左链中的插入位置
|
||||
if (p_left[1] == (int)NULL)
|
||||
break;
|
||||
// count the number of comparisons
|
||||
compare_count++;
|
||||
if (((int *)p_left[1])[0] > p_right[0])
|
||||
break;
|
||||
p_left = (int *)p_left[1];
|
||||
} while (1);
|
||||
// 如果到达左链尾端 , 右链直接接上
|
||||
if (p_left[1] == (int)NULL)
|
||||
{
|
||||
p_left[1] = (int)p_right;
|
||||
break;
|
||||
}
|
||||
int *p_right_temp = p_right;
|
||||
do
|
||||
{ // 寻找右链待插入片段
|
||||
if (p_right_temp[1] == (int)NULL)
|
||||
break;
|
||||
// count the number of comparisons
|
||||
compare_count++;
|
||||
if (((int *)p_right_temp[1])[0] > ((int *)p_left[1])[0])
|
||||
break;
|
||||
p_right_temp = (int *)p_right_temp[1];
|
||||
} while (1);
|
||||
// 完成插入操作
|
||||
int *temp_right_pointer_next = (int *)p_right_temp[1];
|
||||
p_right_temp[1] = p_left[1];
|
||||
p_left[1] = (int)p_right;
|
||||
p_left = p_right_temp;
|
||||
p_right = temp_right_pointer_next;
|
||||
if (p_right == NULL)
|
||||
break;
|
||||
} while (1);
|
||||
int rv = head[1];
|
||||
|
||||
delete head;
|
||||
return (int *)rv;
|
||||
}
|
||||
|
||||
// 归并排序主函数 , 先找链表中点 , 再分别排序 , 最后归并
|
||||
int *msort(int *head)
|
||||
{
|
||||
if (head[1] == (int)NULL)
|
||||
return head;
|
||||
int *stride_2_pointer = head;
|
||||
int *stride_1_pointer = head;
|
||||
do
|
||||
{ // 通过同时进行步长为 1 和步长为 2 的跳转找中点
|
||||
if (stride_2_pointer[1] == (int)NULL)
|
||||
break;
|
||||
stride_2_pointer = (int *)stride_2_pointer[1];
|
||||
if (stride_2_pointer[1] == (int)NULL)
|
||||
break;
|
||||
stride_2_pointer = (int *)stride_2_pointer[1];
|
||||
stride_1_pointer = (int *)stride_1_pointer[1];
|
||||
} while (1);
|
||||
// 拆成两个链表分别排序 , 再归并 。
|
||||
stride_2_pointer = (int *)stride_1_pointer[1];
|
||||
stride_1_pointer[1] = (int)NULL;
|
||||
int *l_head = msort(head);
|
||||
int *r_head = msort(stride_2_pointer);
|
||||
return merge(l_head, r_head);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
FILE *infile, *outfile;
|
||||
int buffer[1001];
|
||||
infile = fopen("a.in", "rb");
|
||||
fread(buffer, 4, 1001, infile);
|
||||
fclose(infile);
|
||||
int N = buffer[0];
|
||||
// create a linked list
|
||||
int *head = new int[2];
|
||||
head[1] = (int)NULL;
|
||||
int *pointer = head;
|
||||
for (int idx = 1; idx <= N; idx++)
|
||||
{
|
||||
pointer[1] = (int)new int[2];
|
||||
pointer = (int *)pointer[1];
|
||||
pointer[0] = buffer[idx];
|
||||
pointer[1] = (int)NULL;
|
||||
}
|
||||
// sort
|
||||
head[1] = (int)msort((int *)head[1]);
|
||||
pointer = head;
|
||||
outfile = fopen("a.out", "wb");
|
||||
// 输出比较次数
|
||||
fwrite(&compare_count, 4, 1, outfile);
|
||||
// wirte the sorted list to file
|
||||
do
|
||||
{
|
||||
pointer = (int *)pointer[1];
|
||||
if (pointer == NULL)
|
||||
break;
|
||||
fwrite(pointer, 4, 1, outfile);
|
||||
} while (1);
|
||||
fclose(outfile);
|
||||
// 本文件用于翻译,没有释放链表内存的操作
|
||||
return 0;
|
||||
}
|
||||
135
1/exp2/merge_sort_runnable.cpp
Normal file
135
1/exp2/merge_sort_runnable.cpp
Normal file
@@ -0,0 +1,135 @@
|
||||
#include "stdio.h" /*
|
||||
|
||||
链表的归并排序的核心是将链表分成前后两段,分别排序后对两个有序链表归并,递归边界是当前链表长度为1。
|
||||
|
||||
!!!注意:此代码为可运行版本,目的是让大家检验自己的实验结果是否正确
|
||||
!!!其中的链表节点是通过结构体实现的,实际汇编的实现中指针也是32位整数,请参考另一个版本的代码(merge_sort.cpp)
|
||||
|
||||
*/
|
||||
|
||||
// 统计待排序数据的比较次数
|
||||
int compare_count = 0;
|
||||
|
||||
// 链表节点, 结构体实现
|
||||
struct Node
|
||||
{
|
||||
int value;
|
||||
Node *next;
|
||||
};
|
||||
|
||||
// 两个有序链表合并,将右链元素插入到左链中 。
|
||||
Node *merge(Node *l_head, Node *r_head)
|
||||
{
|
||||
// 这里构建一个虚拟头结点,方便在第一个元素前插入。
|
||||
Node *head = new Node;
|
||||
head->next = l_head;
|
||||
Node *p_left = head;
|
||||
Node *p_right = r_head;
|
||||
do
|
||||
{
|
||||
do
|
||||
{ // 寻找左链中的插入位置
|
||||
if (p_left->next == (int)NULL)
|
||||
break;
|
||||
compare_count++; // 统计比较次数
|
||||
if ((p_left->next)->value > p_right->value)
|
||||
break;
|
||||
p_left = p_left->next;
|
||||
} while (1);
|
||||
// 如果到达左链尾端,右链直接接上
|
||||
if (p_left->next == NULL)
|
||||
{
|
||||
p_left->next = p_right;
|
||||
break;
|
||||
}
|
||||
Node *p_right_temp = p_right;
|
||||
do
|
||||
{ // 寻找右链待插入片段
|
||||
if (p_right_temp->next == NULL)
|
||||
break;
|
||||
compare_count++; // 统计比较次数
|
||||
if ((p_right_temp->next)->value > (p_left->next)->value)
|
||||
break;
|
||||
p_right_temp = p_right_temp->next;
|
||||
} while (1);
|
||||
// 完成插入操作
|
||||
Node *temp_right_pointer_next = p_right_temp->next;
|
||||
p_right_temp->next = p_left->next;
|
||||
p_left->next = p_right;
|
||||
p_left = p_right_temp;
|
||||
p_right = temp_right_pointer_next;
|
||||
if (p_right == NULL)
|
||||
break;
|
||||
} while (1);
|
||||
Node *rv = head->next;
|
||||
delete head;
|
||||
return rv;
|
||||
}
|
||||
|
||||
// 归并排序主函数,先找链表中点,再分别排序,最后归并
|
||||
Node *msort(Node *head)
|
||||
{
|
||||
if (head->next == NULL)
|
||||
return head;
|
||||
Node *stride_2_pointer = head;
|
||||
Node *stride_1_pointer = head;
|
||||
do
|
||||
{ // 通过同时进行步长为 1 和步长为 2 的跳转找中点
|
||||
if (stride_2_pointer->next == NULL)
|
||||
break;
|
||||
stride_2_pointer = stride_2_pointer->next;
|
||||
if (stride_2_pointer->next == NULL)
|
||||
break;
|
||||
stride_2_pointer = stride_2_pointer->next;
|
||||
stride_1_pointer = stride_1_pointer->next;
|
||||
} while (1);
|
||||
// 拆成两个链表分别排序 , 再归并 。
|
||||
stride_2_pointer = stride_1_pointer->next;
|
||||
stride_1_pointer->next = NULL;
|
||||
Node *l_head = msort(head);
|
||||
Node *r_head = msort(stride_2_pointer);
|
||||
return merge(l_head, r_head);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
FILE *infile, *outfile;
|
||||
int buffer[1001];
|
||||
infile = fopen("a.in", "rb");
|
||||
fread(buffer, 4, 1001, infile);
|
||||
fclose(infile);
|
||||
int N = buffer[0];
|
||||
Node *head = new Node;
|
||||
head->next = NULL;
|
||||
Node *pointer = head;
|
||||
for (int idx = 1; idx <= N; idx++)
|
||||
{
|
||||
pointer->next = new Node;
|
||||
pointer = pointer->next;
|
||||
pointer->value = buffer[idx];
|
||||
pointer->next = NULL;
|
||||
}
|
||||
// 排序
|
||||
head->next = msort(head->next);
|
||||
// 输出到文件
|
||||
pointer = head;
|
||||
outfile = fopen("a.out", "wb");
|
||||
// 输出比较次数
|
||||
fwrite(&compare_count, 4, 1, outfile);
|
||||
do
|
||||
{
|
||||
pointer = pointer->next;
|
||||
if (pointer == NULL)
|
||||
break;
|
||||
fwrite(&(pointer->value), 4, 1, outfile);
|
||||
} while (1);
|
||||
fclose(outfile);
|
||||
// 释放链表内存
|
||||
while (head != NULL)
|
||||
{
|
||||
Node *temp = head;
|
||||
head = head->next;
|
||||
delete temp;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
BIN
1/homework/exp1/a.in
Normal file
BIN
1/homework/exp1/a.in
Normal file
Binary file not shown.
BIN
1/homework/exp1/a.out
Normal file
BIN
1/homework/exp1/a.out
Normal file
Binary file not shown.
42
1/homework/exp1/exp1_1.asm
Normal file
42
1/homework/exp1/exp1_1.asm
Normal file
@@ -0,0 +1,42 @@
|
||||
.data
|
||||
file_buff: .space 8 # A space of 2 bytes
|
||||
.align 3
|
||||
input_file_name: .asciiz "a.in"
|
||||
.align 3
|
||||
output_file_name: .asciiz "a.out"
|
||||
.align 3
|
||||
.text
|
||||
|
||||
la $a0, input_file_name
|
||||
li $a1, 0 # set mode as read
|
||||
li $a2, 0 # meaning nothing, really
|
||||
li $v0, 13 # open file
|
||||
syscall #now $v0 is the file handler
|
||||
|
||||
move $a0, $v0 #move file handler to a0 as first syscall arg
|
||||
la $a1, file_buff
|
||||
li $a2, 8 # read in 8 bytes
|
||||
li $v0, 14
|
||||
syscall
|
||||
li $v0, 16
|
||||
syscall # close file
|
||||
|
||||
la $a0, output_file_name
|
||||
li $a1, 1 # set mode as write
|
||||
li $a2, 0 # meaning nothing, really
|
||||
li $v0, 13 # open file
|
||||
syscall
|
||||
|
||||
move $a0, $v0
|
||||
la $a1, file_buff
|
||||
li $a2, 8 # write 8 bytes
|
||||
li $v0, 15 # write file
|
||||
syscall
|
||||
li $v0, 16
|
||||
syscall
|
||||
|
||||
li $v0, 5 # read integer
|
||||
syscall
|
||||
addi $a0, $v0, 10 # a0 = v0 + 10
|
||||
li $v0, 1 # print integer
|
||||
syscall
|
||||
29
1/homework/exp1/exp1_2.asm
Normal file
29
1/homework/exp1/exp1_2.asm
Normal file
@@ -0,0 +1,29 @@
|
||||
.data
|
||||
.text
|
||||
li $v0, 5 # read in i
|
||||
syscall
|
||||
move $s1, $v0 # use s1 to store i
|
||||
|
||||
li $v0, 5 # read in j
|
||||
syscall
|
||||
move $s2, $v0 # use s2 to store j
|
||||
|
||||
sub $s1, $zero, $s1 # i = -i
|
||||
|
||||
bgez $s2, no_neg_j # if >= 0, then no neg
|
||||
sub $s2, $zero, $s2 # j = -j
|
||||
|
||||
no_neg_j:
|
||||
move $s0, $zero # use s0 as temp, temp = 0
|
||||
count_up_j:
|
||||
bge $s0, $s2, done_count_up # if temp >= j, stop iteration
|
||||
addi $s1, $s1, 1 # i = i + 1
|
||||
addi $s0, $s0, 1 # ++temp
|
||||
j count_up_j
|
||||
|
||||
done_count_up:
|
||||
move $a0, $s1
|
||||
li $v0, 1
|
||||
syscall
|
||||
|
||||
move $v0, $s1 # set return value
|
||||
67
1/homework/exp1/exp1_3.asm
Normal file
67
1/homework/exp1/exp1_3.asm
Normal file
@@ -0,0 +1,67 @@
|
||||
.data
|
||||
.text
|
||||
li $v0, 5 # read in num
|
||||
syscall
|
||||
|
||||
move $s0, $v0 # $s0 is n
|
||||
sll $a0, $v0, 2
|
||||
li $v0, 9 # malloc
|
||||
syscall
|
||||
move $s1, $v0 # $s1 = a
|
||||
|
||||
move $t0, $zero # a0 = 0
|
||||
|
||||
move $t0, $zero # i = 0
|
||||
move $t1, $s1 #t1 = a
|
||||
read_in_num:
|
||||
bge $t0, $s0, done_read_in_num # i >= n, break
|
||||
li $v0, 5 # read in num
|
||||
syscall
|
||||
|
||||
sw $v0, 0($t1) # a[i] = v0
|
||||
addi $t0, $t0, 1 # i++
|
||||
addi $t1, $t1, 4 # t1 += 4
|
||||
j read_in_num
|
||||
|
||||
done_read_in_num:
|
||||
srl $s2, $s0, 1 # s1 = n / 2
|
||||
move $t0, $zero # i = 0
|
||||
move $t1, $s1
|
||||
|
||||
subi $t2, $s0, 1 # t2 = n - 1
|
||||
sll $t2, $t2, 2 # t2 *= 4
|
||||
add $t2, $t2, $s1
|
||||
reverse:
|
||||
bge $t0, $s2, done_reverse # i >= n / 2, break
|
||||
lw $t3, 0($t1) # t3 = a[i]
|
||||
addi $t3, $t3, 1 # t3 += 1
|
||||
|
||||
lw $t4, 0($t2) # t4 = a[n - i - 1]
|
||||
addi $t4, $t4, 1 # t4 += 1
|
||||
|
||||
sw $t4, 0($t1)
|
||||
sw $t3, 0($t2)
|
||||
|
||||
addi $t0, $t0, 1
|
||||
addi $t1, $t1, 4
|
||||
subi $t2, $t2, 4
|
||||
j reverse
|
||||
|
||||
done_reverse:
|
||||
move $t0, $zero
|
||||
move $t1, $s1
|
||||
|
||||
output:
|
||||
bge $t0, $s0, done_output
|
||||
lw $a0, 0($t1)
|
||||
li $v0, 1
|
||||
syscall
|
||||
|
||||
addi $t0, $t0, 1
|
||||
addi $t1, $t1, 4
|
||||
j output
|
||||
|
||||
done_output:
|
||||
li $a0, 0
|
||||
li $v0, 17
|
||||
syscall
|
||||
36
1/homework/exp1/exp1_4.asm
Normal file
36
1/homework/exp1/exp1_4.asm
Normal file
@@ -0,0 +1,36 @@
|
||||
.data
|
||||
|
||||
.text
|
||||
main:
|
||||
li $v0, 5 # read in
|
||||
syscall
|
||||
move $s0, $v0 # s0 is the n
|
||||
move $a0, $s0 # set the first call arg as n
|
||||
jal hanoi # call proc
|
||||
move $a0, $v0 # print out
|
||||
li $v0, 1
|
||||
syscall
|
||||
li $a0, 0
|
||||
li $v0, 17
|
||||
syscall
|
||||
|
||||
hanoi:
|
||||
li $t0, 1
|
||||
ble $a0, $t0, hanoi_bottom # if n <= 1, return
|
||||
j hanoi_recur
|
||||
hanoi_bottom:
|
||||
li $v0, 1 # return 1
|
||||
jr $ra
|
||||
hanoi_recur:
|
||||
subi $sp, $sp, 8 # move sp down by 2 word
|
||||
sw $s0, 4($sp) # first word is the n in caller
|
||||
sw $ra, 0($sp) # second word is the return addr of this callee
|
||||
move $s0, $a0
|
||||
subi $a0, $s0, 1
|
||||
jal hanoi
|
||||
sll $v0, $v0, 1 # hanoi(n - 1) * 2
|
||||
ori $v0, $v0, 1 # hanoi(n - 1) * 2 + 1
|
||||
lw $s0, 4($sp) # reverse s0
|
||||
lw $ra, 0($sp) # reverse ra
|
||||
addi $sp, $sp, 8
|
||||
jr $ra
|
||||
BIN
1/homework/exp2/a.in
Normal file
BIN
1/homework/exp2/a.in
Normal file
Binary file not shown.
BIN
1/homework/exp2/a.out.correct
Normal file
BIN
1/homework/exp2/a.out.correct
Normal file
Binary file not shown.
206
1/homework/exp2/binary_insert_sort.asm
Normal file
206
1/homework/exp2/binary_insert_sort.asm
Normal file
@@ -0,0 +1,206 @@
|
||||
.data
|
||||
compare_count: .word 0
|
||||
num_N: .word 0
|
||||
input_file_name: .asciiz "a.in"
|
||||
.align 2
|
||||
output_file_name: .asciiz "a.out"
|
||||
.align 2
|
||||
space_string: .asciiz " "
|
||||
.align 2
|
||||
newline_string: .asciiz "\r\n"
|
||||
.align 2
|
||||
num_buff: .space 4096
|
||||
.align 2
|
||||
|
||||
.text
|
||||
main:
|
||||
la $a0, input_file_name
|
||||
li $a1, 0
|
||||
li $a2, 0
|
||||
li $v0, 13
|
||||
syscall
|
||||
|
||||
move $a0, $v0 # start to read in N
|
||||
la $a1, num_N
|
||||
li $a2, 4
|
||||
li $v0, 14
|
||||
syscall
|
||||
|
||||
la $t0, num_N # read N * 4 bytes into num_buff
|
||||
lw $a2, 0($t0) # read in num_N
|
||||
sll $a2, $a2, 2 # n * 4 is the bytes to read
|
||||
|
||||
la $a1, num_buff
|
||||
|
||||
li $v0, 14
|
||||
syscall # read in file
|
||||
li $v0, 16
|
||||
syscall # close file
|
||||
# jal print_num_in_buff
|
||||
|
||||
jal insertion_sort
|
||||
|
||||
# jal print_num_in_buff
|
||||
|
||||
la $a0, output_file_name
|
||||
li $a1, 1
|
||||
li $a2, 0
|
||||
li $v0, 13
|
||||
syscall
|
||||
|
||||
move $a0, $v0
|
||||
la $a1, compare_count
|
||||
li $a2, 4
|
||||
li $v0, 15
|
||||
syscall
|
||||
|
||||
la $a1, num_buff
|
||||
la $a2, num_N
|
||||
lw $a2, 0($a2)
|
||||
sll $a2, $a2, 2
|
||||
li $v0, 15
|
||||
syscall
|
||||
|
||||
li $a0, 0
|
||||
li $v0, 17
|
||||
syscall # exit
|
||||
|
||||
insertion_sort:
|
||||
subi $sp, $sp, 4
|
||||
sw $ra, 0($sp)
|
||||
|
||||
la $t0, num_N
|
||||
lw $s0, 0($t0) # n in s0
|
||||
|
||||
li $s1, 1 # i in s1
|
||||
item_loop:
|
||||
bge $s1, $s0, done_item_loop # if i >= n, done loop
|
||||
li $a0, 0
|
||||
subi $a1, $s1, 1
|
||||
move $a2, $s1
|
||||
jal binary_search
|
||||
|
||||
move $a0, $v0
|
||||
move $a1, $s1
|
||||
jal insert
|
||||
|
||||
addi $s1, $s1, 1 # i ++
|
||||
j item_loop
|
||||
done_item_loop:
|
||||
|
||||
lw $ra, 0($sp)
|
||||
addi $sp, $sp, 8
|
||||
jr $ra
|
||||
|
||||
binary_search: # a0: left, a1: right, a2: i
|
||||
subi $sp, $sp, 20
|
||||
sw $s0, 16($sp)
|
||||
sw $s1, 12($sp)
|
||||
sw $s2, 8($sp)
|
||||
sw $s3, 4($sp)
|
||||
sw $ra, 0($sp)
|
||||
|
||||
ble $a0, $a1, in_boundary_binary_search # left <= right, in normal position
|
||||
move $v0, $a0 # now in boundary condition
|
||||
j done_binary_search
|
||||
|
||||
in_boundary_binary_search:
|
||||
move $s0, $a0 # in normal situation
|
||||
move $s1, $a1
|
||||
move $s2, $a2
|
||||
add $s3, $s0, $s1 # s3 = mid = (left + right) >> 1
|
||||
srl $s3, $s3, 1
|
||||
jal add_compare_count
|
||||
|
||||
la $t0, num_buff
|
||||
sll $t1, $s3, 2
|
||||
add $t1, $t1, $t0
|
||||
lw $t1, 0($t1) # t1 = v[mid]
|
||||
sll $t2, $s2, 2
|
||||
add $t2, $t2, $t0
|
||||
lw $t2, 0($t2) # t2 = v[n]
|
||||
ble $t1, $t2, binary_search_right # v[mid] <= v[n], jump to 'else'
|
||||
binary_search_left:
|
||||
subi $a1, $s3, 1
|
||||
jal binary_search
|
||||
j done_binary_search
|
||||
binary_search_right:
|
||||
addi $a0, $s3, 1
|
||||
jal binary_search
|
||||
done_binary_search:
|
||||
lw $s0, 16($sp)
|
||||
lw $s1, 12($sp)
|
||||
lw $s2, 8($sp)
|
||||
lw $s3, 4($sp)
|
||||
lw $ra, 0($sp)
|
||||
addi $sp, $sp, 20
|
||||
jr $ra
|
||||
|
||||
insert: # $a0: int k, $a1: int n
|
||||
subi $sp, $sp, 12
|
||||
sw $s0, 8($sp)
|
||||
sw $s1, 4($sp)
|
||||
sw $ra, 0($sp)
|
||||
|
||||
la $s0, num_buff # s0 = &v[0]
|
||||
|
||||
sll $t0, $a1, 2
|
||||
add $s2, $s0, $t0
|
||||
lw $s2, 0($s2) # s2 = tmp = 'pivot' = v[n]
|
||||
|
||||
subi $s1, $a1, 1 # s1 = i = n - 1
|
||||
|
||||
insert_loop:
|
||||
blt $s1, $a0, done_insert_loop # i < k, done loop
|
||||
sll $t0, $s1, 2
|
||||
add $t0, $s0, $t0 # t0 = &v[i]
|
||||
lw $t1, 0($t0)
|
||||
sw $t1, 4($t0)
|
||||
|
||||
subi $s1, $s1, 1 # i--
|
||||
j insert_loop
|
||||
done_insert_loop:
|
||||
sll $t0, $a0, 2
|
||||
add $t0, $s0, $t0
|
||||
sw $s2, 0($t0) # t0 = &v[k]
|
||||
|
||||
lw $s0, 8($sp)
|
||||
lw $s1, 4($sp)
|
||||
lw $ra, 0($sp)
|
||||
addi $sp, $sp, 12
|
||||
jr $ra
|
||||
|
||||
|
||||
add_compare_count:
|
||||
la $t0, compare_count
|
||||
lw $t1, 0($t0)
|
||||
addi $t1, $t1, 1
|
||||
sw $t1, 0($t0)
|
||||
jr $ra
|
||||
|
||||
print_num_in_buff:
|
||||
la $t0, num_N
|
||||
la $t2, num_buff
|
||||
lw $t0, 0($t0)
|
||||
li $t1, 0
|
||||
print_loop:
|
||||
bge $t1, $t0, done_print_loop
|
||||
|
||||
sll $a0, $t1, 2
|
||||
add $a0, $t2, $a0
|
||||
lw $a0, 0($a0)
|
||||
li $v0, 1
|
||||
syscall
|
||||
|
||||
la $a0, space_string
|
||||
li $v0, 4
|
||||
syscall
|
||||
|
||||
addi $t1, $t1, 1
|
||||
j print_loop
|
||||
|
||||
done_print_loop:
|
||||
la $a0, newline_string
|
||||
li $v0, 4
|
||||
syscall
|
||||
jr $ra
|
||||
189
1/homework/exp2/insert_sort.asm
Normal file
189
1/homework/exp2/insert_sort.asm
Normal file
@@ -0,0 +1,189 @@
|
||||
.data
|
||||
compare_count: .word 0
|
||||
num_N: .word 0
|
||||
input_file_name: .asciiz "a.in"
|
||||
.align 2
|
||||
output_file_name: .asciiz "a.out"
|
||||
.align 2
|
||||
space_string: .asciiz " "
|
||||
.align 2
|
||||
newline_string: .asciiz "\r\n"
|
||||
.align 2
|
||||
num_buff: .space 4096
|
||||
.align 2
|
||||
|
||||
.text
|
||||
main:
|
||||
la $a0, input_file_name
|
||||
li $a1, 0
|
||||
li $a2, 0
|
||||
li $v0, 13
|
||||
syscall
|
||||
|
||||
move $a0, $v0 # start to read in N
|
||||
la $a1, num_N
|
||||
li $a2, 4
|
||||
li $v0, 14
|
||||
syscall
|
||||
|
||||
la $t0, num_N # read N * 4 bytes into num_buff
|
||||
lw $a2, 0($t0) # read in num_N
|
||||
sll $a2, $a2, 2 # n * 4 is the bytes to read
|
||||
|
||||
la $a1, num_buff
|
||||
|
||||
li $v0, 14
|
||||
syscall # read in file
|
||||
li $v0, 16
|
||||
syscall # close file
|
||||
|
||||
jal insertion_sort
|
||||
|
||||
la $a0, output_file_name
|
||||
li $a1, 1
|
||||
li $a2, 0
|
||||
li $v0, 13
|
||||
syscall
|
||||
|
||||
move $a0, $v0
|
||||
la $a1, compare_count
|
||||
li $a2, 4
|
||||
li $v0, 15
|
||||
syscall
|
||||
|
||||
la $a1, num_buff
|
||||
la $a2, num_N
|
||||
lw $a2, 0($a2)
|
||||
sll $a2, $a2, 2
|
||||
li $v0, 15
|
||||
syscall
|
||||
|
||||
li $a0, 0
|
||||
li $v0, 17
|
||||
syscall # exit
|
||||
|
||||
insertion_sort:
|
||||
subi $sp, $sp, 4
|
||||
sw $ra, 0($sp)
|
||||
|
||||
la $t0, num_N
|
||||
lw $s0, 0($t0) # n in s0
|
||||
|
||||
li $s1, 1 # i in s1
|
||||
item_loop:
|
||||
bge $s1, $s0, done_item_loop # if i >= n, done loop
|
||||
move $a0, $s1
|
||||
jal search
|
||||
|
||||
move $a0, $v0
|
||||
move $a1, $s1
|
||||
jal insert
|
||||
|
||||
addi $s1, $s1, 1 # i ++
|
||||
j item_loop
|
||||
done_item_loop:
|
||||
|
||||
lw $ra, 0($sp)
|
||||
addi $sp, $sp, 8
|
||||
jr $ra
|
||||
|
||||
search: # $a0: int n
|
||||
subi $sp, $sp, 12
|
||||
sw $s0, 8($sp)
|
||||
sw $s1, 4($sp)
|
||||
sw $ra, 0($sp)
|
||||
|
||||
la $s0, num_buff
|
||||
sll $t0, $a0, 2
|
||||
add $s2, $s0, $t0
|
||||
lw $s2, 0($s2) # s2 = tmp = v[n]
|
||||
|
||||
subi $s1, $a0, 1 # i = n - 1
|
||||
search_loop:
|
||||
bltz $s1, done_search_loop # i < 0, done loop
|
||||
jal add_compare_count
|
||||
|
||||
sll $t0, $s1, 2
|
||||
add $t0, $s0, $t0
|
||||
lw $t0, 0($t0) # t0 = v[i]
|
||||
ble $t0, $s2, done_search_loop # if v[i] <= tmp, break
|
||||
|
||||
subi $s1, $s1, 1 # i--
|
||||
j search_loop
|
||||
|
||||
done_search_loop:
|
||||
addi $v0, $s1, 1 # return i + 1
|
||||
|
||||
lw $s0, 8($sp)
|
||||
lw $s1, 4($sp)
|
||||
lw $ra, 0($sp)
|
||||
addi $sp, $sp, 12
|
||||
jr $ra
|
||||
insert: # $a0: int k, $a1: int n
|
||||
subi $sp, $sp, 12
|
||||
sw $s0, 8($sp)
|
||||
sw $s1, 4($sp)
|
||||
sw $ra, 0($sp)
|
||||
|
||||
la $s0, num_buff # s0 = &v[0]
|
||||
|
||||
sll $t0, $a1, 2
|
||||
add $s2, $s0, $t0
|
||||
lw $s2, 0($s2) # s2 = tmp = 'pivot' = v[n]
|
||||
|
||||
subi $s1, $a1, 1 # s1 = i = n - 1
|
||||
|
||||
insert_loop:
|
||||
blt $s1, $a0, done_insert_loop # i < k, done loop
|
||||
sll $t0, $s1, 2
|
||||
add $t0, $s0, $t0 # t0 = &v[i]
|
||||
lw $t1, 0($t0)
|
||||
sw $t1, 4($t0)
|
||||
|
||||
subi $s1, $s1, 1 # i--
|
||||
j insert_loop
|
||||
done_insert_loop:
|
||||
sll $t0, $a0, 2
|
||||
add $t0, $s0, $t0
|
||||
sw $s2, 0($t0) # t0 = &v[k]
|
||||
|
||||
lw $s0, 8($sp)
|
||||
lw $s1, 4($sp)
|
||||
lw $ra, 0($sp)
|
||||
addi $sp, $sp, 12
|
||||
jr $ra
|
||||
|
||||
|
||||
add_compare_count:
|
||||
la $t0, compare_count
|
||||
lw $t1, 0($t0)
|
||||
addi $t1, $t1, 1
|
||||
sw $t1, 0($t0)
|
||||
jr $ra
|
||||
|
||||
print_num_in_buff:
|
||||
la $t0, num_N
|
||||
la $t2, num_buff
|
||||
lw $t0, 0($t0)
|
||||
li $t1, 0
|
||||
print_loop:
|
||||
bge $t1, $t0, done_print_loop
|
||||
|
||||
sll $a0, $t1, 2
|
||||
add $a0, $t2, $a0
|
||||
lw $a0, 0($a0)
|
||||
li $v0, 1
|
||||
syscall
|
||||
|
||||
la $a0, space_string
|
||||
li $v0, 4
|
||||
syscall
|
||||
|
||||
addi $t1, $t1, 1
|
||||
j print_loop
|
||||
|
||||
done_print_loop:
|
||||
la $a0, newline_string
|
||||
li $v0, 4
|
||||
syscall
|
||||
jr $ra
|
||||
253
1/homework/exp2/merge_sort.asm
Normal file
253
1/homework/exp2/merge_sort.asm
Normal file
@@ -0,0 +1,253 @@
|
||||
.data
|
||||
compare_count: .word 0
|
||||
num_N: .word 0
|
||||
input_file_name: .asciiz "a.in"
|
||||
.align 2
|
||||
output_file_name: .asciiz "a.out"
|
||||
.align 2
|
||||
space_string: .asciiz " "
|
||||
.align 2
|
||||
newline_string: .asciiz "\r\n"
|
||||
.align 2
|
||||
num_buff: .space 4096
|
||||
.align 2
|
||||
|
||||
.text
|
||||
main:
|
||||
la $a0, input_file_name
|
||||
li $a1, 0
|
||||
li $a2, 0
|
||||
li $v0, 13
|
||||
syscall
|
||||
|
||||
move $a0, $v0 # start to read in N
|
||||
la $a1, num_N
|
||||
li $a2, 4
|
||||
li $v0, 14
|
||||
syscall
|
||||
|
||||
la $t0, num_N # read N * 4 bytes into num_buff
|
||||
lw $a2, 0($t0) # read in num_N
|
||||
sll $a2, $a2, 2 # n * 4 is the bytes to read
|
||||
|
||||
la $a1, num_buff
|
||||
|
||||
li $v0, 14
|
||||
syscall # read in file
|
||||
li $v0, 16
|
||||
syscall # close file
|
||||
|
||||
la $t0, num_N
|
||||
lw $s0, 0($t0) # s0 = N
|
||||
li $a0, 8
|
||||
li $v0, 9
|
||||
syscall
|
||||
move $s2, $v0 # headptr in s2
|
||||
move $s3, $s2 # curnodeptr = headptr
|
||||
|
||||
li $s1, 0 # s1 = index
|
||||
la $t0, num_buff
|
||||
create_linked_list:
|
||||
bge $s1, $s0, done_create_linked_list
|
||||
li $v0, 9
|
||||
syscall # new int[2]
|
||||
|
||||
sw $v0, 4($s3) # curnodeptr[1] = new int[2]
|
||||
move $s3, $v0 # curnodeptr = curnodeptr[1]
|
||||
|
||||
sll $t1, $s1, 2 # curnodeptr[0] = num_buffer[index]
|
||||
add $t1, $t0, $t1
|
||||
lw $t1, 0($t1)
|
||||
sw $t1, 0($s3)
|
||||
|
||||
sw $zero, 4($s3) # curnodeptr[1] = NULL
|
||||
|
||||
addi $s1, $s1, 1
|
||||
j create_linked_list
|
||||
done_create_linked_list:
|
||||
# lw $a0, 4($s2) #a0 = headnodeptr[1]
|
||||
# jal print_num
|
||||
lw $a0, 4($s2) #a0 = headnodeptr[1]
|
||||
jal merge_sort
|
||||
sw $v0, 4($s2)
|
||||
move $s1, $s2 # curptr = headptr
|
||||
# lw $a0, 4($s2) #a0 = headnodeptr[1]
|
||||
# jal print_num
|
||||
|
||||
la $a0, output_file_name
|
||||
li $a1, 1
|
||||
li $a2, 0
|
||||
li $v0, 13
|
||||
syscall
|
||||
|
||||
move $a0, $v0
|
||||
la $a1, compare_count
|
||||
li $a2, 4
|
||||
li $v0, 15
|
||||
syscall
|
||||
|
||||
write_linked_list:
|
||||
lw $s1, 4($s1) # curptr = curptr[1]
|
||||
beq $s1, $zero, done_write_linked_list
|
||||
move $a1, $s1
|
||||
li $v0, 15
|
||||
syscall
|
||||
j write_linked_list
|
||||
done_write_linked_list:
|
||||
li $v0, 16
|
||||
syscall
|
||||
|
||||
li $a0, 0
|
||||
li $v0, 17
|
||||
syscall # exit
|
||||
|
||||
merge_sort: # a0: headnodeptr
|
||||
subi $sp, $sp, 20
|
||||
sw $s0, 16($sp)
|
||||
sw $s1, 12($sp)
|
||||
sw $s2, 8($sp)
|
||||
sw $s3, 4($sp)
|
||||
sw $ra, 0($sp)
|
||||
|
||||
lw $t0, 4($a0) # t0 = headnodeptr[1]
|
||||
bne $t0, $zero, valid_head # if headnodeptr[1] != NULL, valid head
|
||||
move $v0, $a0 # no valid head
|
||||
j done_merge_sort
|
||||
valid_head:
|
||||
move $s1, $a0 # stride 1 pointer
|
||||
move $s2, $a0 # stride 2 pointer
|
||||
find_mid:
|
||||
lw $s2, 4($s2) # s2 = s2[1]
|
||||
beq $s2, $zero, done_find_mid # s2 == NULL, break
|
||||
lw $s2, 4($s2) # s2 = s2[1]
|
||||
beq $s2, $zero, done_find_mid # s2 == NULL, break
|
||||
lw $s1, 4($s1)
|
||||
j find_mid
|
||||
done_find_mid:
|
||||
lw $s2, 4($s1) # now s2 is the headnodeptr of the right part
|
||||
sw $zero, 4($s1)
|
||||
jal merge_sort # no need to set a0 to head, it already is
|
||||
move $s1, $v0 # save the result of first merge_sort to s1
|
||||
|
||||
move $a0, $s2
|
||||
jal merge_sort # merge_sort for right part
|
||||
|
||||
# move $a0, $s1
|
||||
# jal print_num
|
||||
|
||||
# move $a0, $v0
|
||||
# jal print_num
|
||||
|
||||
move $a0, $s1
|
||||
move $a1, $v0
|
||||
jal merge_list
|
||||
|
||||
done_merge_sort:
|
||||
lw $s0, 16($sp)
|
||||
lw $s1, 12($sp)
|
||||
lw $s2, 8($sp)
|
||||
lw $s3, 4($sp)
|
||||
lw $ra, 0($sp)
|
||||
addi $sp, $sp, 20
|
||||
jr $ra
|
||||
|
||||
merge_list: # a0: l_head, a1: r_head
|
||||
subi $sp, $sp, 28
|
||||
sw $s0, 24($sp)
|
||||
sw $s1, 20($sp)
|
||||
sw $s2, 16($sp)
|
||||
sw $s3, 12($sp)
|
||||
sw $s4, 8($sp)
|
||||
sw $s5, 4($sp)
|
||||
sw $ra, 0($sp)
|
||||
|
||||
move $s0, $a0 # lheadptr
|
||||
move $s1, $a1 # s1 = rheadptr
|
||||
|
||||
li $a0, 8
|
||||
li $v0, 9
|
||||
syscall # create dummy node
|
||||
|
||||
sw $s0, 4($v0) # headnodeptr[1] = lheadptr
|
||||
move $s0, $v0 # p_left = headnodeptr; p_right = rightptr, no change.
|
||||
move $s7, $v0 # head
|
||||
do_merge_list: # outer while
|
||||
find_left_merge_pos:
|
||||
lw $s2, 4($s0) #p_left[1]
|
||||
beq $s2, $zero, direct_add_right_part
|
||||
jal add_compare_count
|
||||
lw $s2, 0($s2) # (p_left[1])[0]
|
||||
lw $t0, 0($s1) # p_right[0]
|
||||
bgt $s2, $t0, no_direct_add_right_part
|
||||
lw $s0, 4($s0)
|
||||
j find_left_merge_pos
|
||||
direct_add_right_part:
|
||||
sw $s1, 4($s0)
|
||||
j done_do_merge_list
|
||||
no_direct_add_right_part:
|
||||
move $s2, $s1 # p_right_temp
|
||||
lw $s5, 4($s0)
|
||||
lw $s5, 0($s5) # (p_left[1])[0]
|
||||
find_right_merge_pos:
|
||||
lw $s3, 4($s2) # p_right_temp[1]
|
||||
beq $s3, $zero, done_find_right_merge_pos
|
||||
jal add_compare_count
|
||||
lw $s4, 0($s3) # (p_right_temp[1])[0]
|
||||
bgt $s4, $s5, done_find_right_merge_pos
|
||||
move $s2, $s3 # p_right_temp = p_right_temp[1]
|
||||
j find_right_merge_pos
|
||||
done_find_right_merge_pos:
|
||||
move $s4, $s3 # temp_right_pointer_next
|
||||
lw $t0, 4($s0) # p_left[1]
|
||||
sw $t0, 4($s2) # p_right_temp[1] = p_left[1]
|
||||
sw $s1, 4($s0) # p_left[1] = p_right
|
||||
move $s0, $s2
|
||||
move $s1, $s4
|
||||
beq $s1, $zero, done_do_merge_list
|
||||
j do_merge_list
|
||||
done_do_merge_list:
|
||||
lw $v0, 4($s7)
|
||||
|
||||
done_merge_list:
|
||||
lw $s0, 24($sp)
|
||||
lw $s1, 20($sp)
|
||||
lw $s2, 16($sp)
|
||||
lw $s3, 12($sp)
|
||||
lw $s4, 8($sp)
|
||||
lw $s5, 4($sp)
|
||||
lw $ra, 0($sp)
|
||||
addi $sp, $sp, 28
|
||||
jr $ra
|
||||
|
||||
add_compare_count:
|
||||
la $t0, compare_count
|
||||
lw $t1, 0($t0)
|
||||
addi $t1, $t1, 1
|
||||
sw $t1, 0($t0)
|
||||
jr $ra
|
||||
|
||||
print_num: #a0: headptr
|
||||
subi $sp, $sp, 8
|
||||
sw $t0, 4($sp)
|
||||
sw $v0, 0($sp)
|
||||
|
||||
move $t0, $a0
|
||||
print_loop:
|
||||
lw $a0, 0($t0)
|
||||
li $v0, 1
|
||||
syscall
|
||||
la $a0, space_string
|
||||
li $v0, 4
|
||||
syscall
|
||||
lw $t0, 4($t0)
|
||||
beq $t0, $zero, done_print_num
|
||||
j print_loop
|
||||
done_print_num:
|
||||
la $a0, newline_string
|
||||
li $v0, 4
|
||||
syscall
|
||||
|
||||
lw $t0, 4($sp)
|
||||
lw $v0, 0($sp)
|
||||
addi $sp, $sp, 8
|
||||
jr $ra
|
||||
85
1/homework/report.tex
Normal file
85
1/homework/report.tex
Normal file
@@ -0,0 +1,85 @@
|
||||
\documentclass[11pt, a4paper]{article}
|
||||
\usepackage[UTF8]{ctex}
|
||||
\usepackage{geometry}
|
||||
\usepackage[inline]{enumitem}
|
||||
\usepackage{amsmath}
|
||||
\usepackage{float}
|
||||
\usepackage{listings}
|
||||
\usepackage{fontspec}
|
||||
\usepackage{xcolor}
|
||||
|
||||
% \newfontfamily\codefont[Ligatures=ResetAll]{Fira Code}[Contextuals={Alternate}]
|
||||
\newfontfamily\codefont{Cascadia Code}
|
||||
|
||||
\lstset{
|
||||
basicstyle = \small\codefont,
|
||||
% ---
|
||||
tabsize = 4,
|
||||
showstringspaces = false,
|
||||
numbers = left,
|
||||
numberstyle = \codefont,
|
||||
% ---
|
||||
breaklines = true,
|
||||
captionpos = t,
|
||||
% ---
|
||||
frame = l,
|
||||
flexiblecolumns,
|
||||
columns = fixed,
|
||||
}
|
||||
|
||||
\lstdefinestyle{asmstyle}{
|
||||
% basicstyle = \small\codefont,
|
||||
keywordstyle=\bfseries\color{green!40!black},
|
||||
commentstyle=\color{purple!40!black},
|
||||
identifierstyle=\color{blue!80!white},
|
||||
}
|
||||
|
||||
\title{\textbf{Report for First Assembly Homework}}
|
||||
\author{2022010639 高艺轩}
|
||||
\date{}
|
||||
|
||||
\begin{document}
|
||||
\maketitle
|
||||
\section{Basic Exercises}
|
||||
\subsection{System Call}
|
||||
The code is essentially a set of system calls. Set the values in \lstinline{$a0, $a1, $a2} as the arguments to pass to the operation system, and use \lstinline{$v0} to change the exact systemcall.
|
||||
|
||||
These systemcalls first open file as read only, then read the contents into the memory; close the file, then open another file in write only mode and write the content just read from the other file.
|
||||
|
||||
The last two systemcalls are reading from \lstinline{stdin} and output to \lstinline{stdout}, respectively.
|
||||
|
||||
\subsection{Loop and Branch}
|
||||
The \lstinline{for} loop and \lstinline{if} clause in high level programming language is written in a way that we write the action to do when the expression is satisfied at the top, and then write the other part after that. However, to achieve similar structure in assembly code, we have to compose the logic in the way of ``If the expression is NOT met, then jump further away so the instructions right behind this jump instruction is NOT executed'', and by this way, when the expression is met, \lstinline{pc} won't be altered and the code below will be executed.
|
||||
|
||||
The program first read in \lstinline{i} and \lstinline{j} from \lstinline{stdin}, then use a \lstinline{bgez} to decided whether \lstinline{j = -j} needed to be executed. Then, set a register as temp, and count it up to add 1 to \lstinline{i} every time until temp is greater than or equal to (\lstinline{bge}) \lstinline{j}. Lastly, print out the result and set the return value.
|
||||
|
||||
\subsection{Array and Pointer}
|
||||
First, read in the total number \lstinline{n} of the upcoming numbers; Then, request \lstinline{n << 2} bytes of space to store the numbers. Use \lstinline{$t0} as the counter, and \lstinline{$t1} as the pointer, write the number read into memory. Doing the reverse is similar to this. Every iteration adds \lstinline{$t1} by 4 and subtracts \lstinline{$t2} by 4 so that \lstinline{a[i]} and \lstinline{a[n - i - 1]} can be accessed. At last, cycle through the number once more to output the results.
|
||||
|
||||
\subsection{Function Call}
|
||||
Function call is actually very similar to what it is in higher level language. The only difference is that inside a procedure call, first move \lstinline{$sp} by some distance and store all the registers that are required to be preserved but also used by this procedure call, including \lstinline{$ra}. Then write the procedure as if it is a normal program, the arguments of the call is stored in \lstinline{$a0, $a1, $a2} and should be copied to saved registers if needed later. At the end of the procedure, save the return value to \lstinline{$v0}, restore all the saved register value from stack and restore \lstinline{$sp} then call \lstinline{jr $ra} to return.
|
||||
|
||||
\section{Practical Application}
|
||||
\subsection{Direct Insertion Sort}
|
||||
In \lstinline{insertion_sort}, \lstinline{$s0} is the \lstinline{n}, \lstinline{$s1} is the \lstinline{i} in \lstinline{for} loop. For every element in the list, the procedure uses \lstinline{search} to find its correct position, and use insert to insert it into that position.
|
||||
|
||||
In \lstinline{search}, \lstinline{$s0} is \lstinline{&v[0]} and \lstinline{$s2} is \lstinline{v[n]}, \lstinline{$s1} is \lstinline{i} in the \lstinline{search_loop}. The procedure finds the first number that is smaller than the target number, and return the address of one after this smaller number.
|
||||
|
||||
In \lstinline{insert}, \lstinline{$s0 = &v[0]}, \lstinline{$s2 = v[n]}, \lstinline{$s1 = i}, string from \lstinline{n - 1}. The procedure moves everything after the target's correct position one slot backward, and then insert the target into its correct position.
|
||||
|
||||
In \lstinline{add_compare_count}, the procedure loads the stored compare count, add 1 to it, and then write it back to memory.
|
||||
|
||||
\lstinline{print_num_in_buff} is a procedure used for debugging. It prints out all the number in the number buffer, seperated by space and ended by \lstinline{\r\n}.
|
||||
|
||||
\subsection{Binary Insertion Sort}
|
||||
The overall design and structure of the program is same as the `Direct Insertion Sort'. The only difference is that the \lstinline{search} procedure now uses binary search to search for the correct position of the target number.
|
||||
|
||||
In the new \lstinline{binary_search} procedure, \lstinline{$s1 = left}, \lstinline{$s2 = right}, \lstinline{$s3 = mid}, and \lstinline{$t0 = &v[0]}, \lstinline{$t1 = v[mid]}, \lstinline{$t2 = v[n] = target_number}. Every time the procedure finds the number in the middle of left and right and compare it with the target number; if the middle number is larger, then further search for left part; if the middle number is smaller, then further search for right part. Do this recursively until the left bound is larger than right bound, which means the left bound is the position to insert this target number.
|
||||
|
||||
\subsection{Merge Sort}
|
||||
The C++ code uses linked list, and thus the \lstinline{main} part of the code have to create the linked list after reading the file into the memory. For every number, allocate a new node on heap, then save the pointer and content. Then it calls \lstinline{merge_sort} and save the sort result into file.
|
||||
|
||||
In \lstinline{merge_sort}, \lstinline{$s1} is the stride 1 pointer and \lstinline{$s2} is the stride 2 pointer that goes 2 steps every 1 step the stride 1 pointer tooks. When stride 2 pointer reaches the end of the list, stride 1 pointer is pointing at the middle of the list. Then it breaks the list at the middle, and calls \lstinline{merge_sort} on both parts. Then, use \lstinline{merge_list} to merge back the two parts into a ordered list.
|
||||
|
||||
In \lstinline{merge_list}, \lstinline{$s0} is the \lstinline{p_left}, \lstinline{$s1} is the \lstinline{p_right}, and \lstinline{$s7} is the \lstinline{head}. \lstinline{$s2, $s3, $s4, $s5} are used according to the needs, they are typically \lstinline{p_left[1]}, or \lstinline{(p_left[1])[0]}, or \lstinline{p_right_temp}, which are labeled in comments. In essence, the proceture takes two ordered list and reconnect them to combine them into one ordered list.
|
||||
\end{document}
|
||||
Reference in New Issue
Block a user