Lab 6 C重写Lab1-5
Purpose
使用高级编程语言(例如C / C++)来实现以前编写的所有代码。请注意,该算法需要与之前使用的算法一致
condition:
- 明确禁止使用LC3不直接支持的
*、/、%>><<
等操作及等效库函数; - 可以使用
+,-,=,++,--,==,!=,<,>,<=,>=,&,|,~
; - 可以使用
for 、 while 、do while 、if 、continue 、break、switch case
; - 可以定义不违反上述规则的帮助功能。
several examples:
Procedure
lab1:counting how many 1
int16_t lab1(int16_t a, int16_t b) {// initializeint16_t res = 0, ptr = 1;// calculationwhile(b--){if(a&ptr)res++;ptr += ptr ;}// return valuereturn res;
}
第一个实验是统计给定数中低b位的数字,在汇编中使用的算法是利用与操作用一个探测数从最低位与指定数与,结果为1即说明该位为1,重复此操作直到循环结束,其中res存放结果,ptr为探测数,左移操作在这里使用自加实现,循环结束返回res即可
lab2:a variant of the fibonacci sequence
int16_t lab2(int16_t p, int16_t q, int16_t n) {// initializeint16_t R1 = p-1, R2 = q, R3 = n-2;int16_t R0 = 1, R4 = 1, R5 = -q, R6 = 1;// R0: F(n-2)%p R4:F(n-1) R6:F(n-1)%q// R1: p-1 R2:q R3:n R5:-q// calculationmod:R6 += R0;R3 -= 1;if(R3 < 0) return R6;R0 = R4 & R1;R4 = R6;re:R6 += R5;if(R6>=0) goto re;R6 += R2;goto mod;// return value
}
第二个实验是计算修改过的斐波那契数,在这里我直接模拟当时汇编代码的实现,使用R0-R7共八个寄存器,其中使用if语句代替判断条件码,同样使用label标记代码段,使用goto语句实现跳转,取模操作则是与汇编中的方法相同,对于2的幂次数,使用与运算取模,不是则循环减,直至负数,再加上一个模数即可
lab3: longest duplicate substring
int16_t lab3(int16_t n, char s[]) {// initializeint16_t res = 1,temp = res;// calculationfor(int i = 0,j = 1; j <= n; i++,j++ ){if(s[i] == s[j])res++;else{if(res > temp) temp = res;res = 1;}}// return valueif(temp>res) return temp;else return res;
}
第三个实验是统计给定字符串中最长的重复子串长度,在原汇编实现时,我使用的是双指针比较两个字符,在c中实现更便捷,在循环中使用两个变量i、j,其中i在前j在后,每次比较两者是否相同,使用res和temp记录当前重复字符的个数,由于最少一个相同字符,所以初始化为1,初始使用res记录,直到出现不同的字符,此时res置为1,判断两者的较大值,temp记录两者的较大值,最后循环结束,取两者中较大值即为结果
lab4:sort and count
void lab4(int16_t score[], int16_t *a, int16_t *b) {// initialize(*a) =0, (*b) = 0;int16_t temp;//冒泡排序for(int i = 1; i <=15; i++) {for (int j = 0; j <= 15 - i; j++) {if (score[j] > score[j + 1]) {temp = score[j];score[j] = score[j + 1];score[j + 1] = temp;}}}for(int i = 12; i <=15; i++){if (score[i] >= 85)(*a)++;else if (score[i] >= 75)(*b)++;}for(int i = 8; i<=11 ;i++)if(score[i] >= 75)(*b)++;
}
第四个实验是对给定的成绩进行排序,并统计“A,B”等级的个数,在汇编代码中,使用冒泡排序先对成绩序列进行排序,再统计前四个和前八个符合范围的个数,在排序后的第12-15个是最高的四个,其中大于等于85分的都是A,否则大于等于75的为B,而8-11是次高的四个,其中大于等于75的都是B
Result
Debug:
过程中遇到的主要问题有:
lab3中 res应该要重新设置为1,一开始设置为0导致每个的结果都少了1
else{if(res > temp) temp = res;res = 1;}
lab4中,由于传入的参数类型为指针类型int16_t *a, int16_t *b
,所以后面对其的操作应该要使用(*a) (*b)
,否则会出现结果溢出int16的范围问题
Test:
Judge:
将代码整理如下:
int16_t lab1(int16_t a, int16_t b) {// initializeint16_t res = 0, ptr = 1;// calculationwhile(b--){if(a&ptr)res++;ptr += ptr ;}// return valuereturn res;
}int16_t lab2(int16_t p, int16_t q, int16_t n) {// initializeint16_t R1 = p-1, R2 = q, R3 = n-2;int16_t R0 = 1, R4 = 1, R5 = -q, R6 = 1;// R0: F(n-2)%p R4:F(n-1) R6:F(n-1)%q// R1: p-1 R2:q R3:n R5:-q// calculationmod:R6 += R0;R3 -= 1;if(R3 < 0) return R6;R0 = R4 & R1;R4 = R6;re:R6 += R5;if(R6>=0) goto re;R6 += R2;goto mod;// return value
}int16_t lab3(int16_t n, char s[]) {// initializeint16_t res = 1,temp = res;// calculationfor(int i = 0,j = 1; j <= n; i++,j++ ){if(s[i] == s[j])res++;else{if(res > temp) temp = res;res = 1;}}// return valueif(temp>res) return temp;else return res;
}void lab4(int16_t score[], int16_t *a, int16_t *b) {// initialize(*a) =0, (*b) = 0;int16_t temp;//冒泡排序for(int i = 1; i <=15; i++) {for (int j = 0; j <= 15 - i; j++) {if (score[j] > score[j + 1]) {temp = score[j];score[j] = score[j + 1];score[j + 1] = temp;}}}for(int i = 12; i <=15; i++){if (score[i] >= 85)(*a)++;else if (score[i] >= 75)(*b)++;}for(int i = 8; i<=11 ;i++)if(score[i] >= 75)(*b)++;// calculation// return value
}
使用test文件评测结果如下,正常运行,输出正确。
Summary
-
What is the difference between programming in a high-level language andprogramming in LC3 assembly language?
高级语言可读性强,对程序员友好,提供的功能更全面更强大,适合编写较大的项目以及程序,但运行效率可能较低,而汇编语言可读性差,编写工程量大的代码时十分费劲,指令也很多而繁琐,许多细节都要程序员自己手动配置,对程序员不友好,但执行效率高 -
What instructions do you think need to be added to LC3? (Hint: You can thinkabout the previous labs and what instructions could be added to greatly simplifythe previous programming)
乘法指令和除法指令,这两个指令都需要通过循环以及其他各种指令来实现,如果多次用到那么程序会很臃肿并且写起来很麻烦,所以添加这个指令比较重要 -
Is there anything you need to learn from LC3 for the high-level language you use?
从LC-3,我学习到各种语言执行时机器码是如何变化的,特别是补码的运算,我觉得十分巧妙,以及左移右移实现的乘除操作,通过与运算等判断某一位的状态,这让我在写高级语言程序时能够更清楚其中的原理