OS pre 知识点和解题过程分享
OS-pre
实验经验
建议用 vim,vim 有很多其他的功能可以用文件加入啊,nano虽然感觉没vim好用,但是软件工程基础还是要求使用nano的,用了vim命令显示未知指令,不过软工是GUI,实在不熟练也可以直接改文件,但是会卡。lab0 一定要熟练 grep、shell 和 Makefile 文件的创建,真的要熟练才能及时写好,不然实验很麻烦。Git 因为有软工第一次实验,所以其实还好。
C-exercise
认真阅读假期预习和 guide book,按照给的操作进入git仓库根目录也就是/24373433,再vim blib.c进入编辑就行,i进入插入模式。esc键退出,函数很简单,补充完整就好,然后make编译,再make run运行,出现 pass 就说明测试点过了,没过用 make dbg 调试一下就好了。
make-exercise
Makefile示例
1CC := gcc
2CFLAGS := -O2 -Wall
3.PHONY: out clean case_add case_sub case_mul case_div case_all
4# 用.PHONY避开文件存在的检查,伪目标,就不会检查同名文件是否存在。
5casegen: casegen.c
6 $(CC) $(CFLAGS) -o $@ $<
7#gcc -O2 -Wall -o casegen casegen.c. $@=当前规则目标名,$<=第一个依赖文件
8calc: calc.c
9 $(CC) $(CFLAGS) -o $@ $<
10# 同上
11# 100 个加/减/乘/除样例,各自输出到对应文件
12case_add: casegen
13 ./casegen add 100 > case_add
14
15case_sub: casegen
16 ./casegen sub 100 > case_sub
17
18case_mul: casegen
19 ./casegen mul 100 > case_mul
20
21case_div: casegen
22 ./casegen div 100 > case_div
23# 这部分在下面分析casegen.c里详细讲述
24# 合并成 400 个样例
25case_all: case_add case_sub case_mul case_div
26 cat case_add case_sub case_mul case_div > case_all
27# make 或 make out:用 calc 计算 case_all,输出 out
28out: calc case_all
29 ./calc < case_all > out
30# 默认目标
31all: out
32clean:
33 rm -f case_* out casegen calc
calc.c
1#include <stdio.h>
2#include <string.h>
3
4int main() {
5 char op[5];
6 int a, b;
7 while (scanf("%s%d%d", op, &a, &b) == 3) {
8 if (!strcmp(op, "add")) {
9 printf("%d\n", a + b);
10 } else if (!strcmp(op, "sub")) {
11 printf("%d\n", a - b);
12 } else if (!strcmp(op, "mul")) {
13 printf("%d\n", a * b);
14 } else if (!strcmp(op, "div")) {
15 printf("%d\n", a / b);
16 }
17 }
18 return 0;
19}
casegen.c
1const char *ops[] = {"add", "sub", "mul", "div"};
2
3uint32_t xrand() {
4 /* Algorithm "xor" from p. 4 of Marsaglia, "Xorshift RNGs" */
5 static uint32_t x = 2024;
6 x ^= x << 13;
7 x ^= x >> 17;
8 x ^= x << 5;
9 return x;
10}
11
12void help() {
13 printf("Usage: ./casegen <op> <num>\n"
14 "Available <op>s: add, sub, mul, div.\n"
15 "<num>: The number of test cases generated (a positive integer).\n");
16}//这里写了命令的用法,usage:后面就是输出样例的指令,<op>表示操作名,<num>表示生成的个数,这就是为什么上面那么写
17
18int is_op_legal(char *op) {
19 size_t sz = sizeof(ops) / sizeof(ops[0]);
20 for (int i = 0; i < sz; i++) {
21 if (strcmp(op, ops[i]) == 0) {
22 return 1;
23 }
24 }
25 return 0;
26}
27
28int get_num(char *str_num, int *num) {
29 *num = strtol(str_num, NULL, 10);
30 return *num > 0;
31}
32
33int main(int argc, char **argv) {
34 int num;
35 if (argc != 3 || !is_op_legal(argv[1]) || !get_num(argv[2], &num)) {
36 help();
37 return 1;
38 }
39 while (num--) {
40 printf("%s %u %u\n", argv[1], xrand() % 10000 + 1, xrand() % 10000 + 1);
41 }
42 return 0;
43}
mips-exercise
没有很多要说的,中文翻译过来一般都可以。
MIPS 汇编 (MARS)
1#include <asm/asm.h>
2.data
3str:
4.asciiz "Hello World\n" # Null-terminated string "Hello World" stored at label 'str'
5.align 2 # align to 4-byte boundary (2^2)
6var:
7.byte 3 # correctly aligned byte: 3
8/* '<x>' 是需要替换的内容. */
9/* use '.align <x>' to align the following words to 1-byte(希望是1字节一个对齐,所以就是.align 0) boundary (disabling word-alignment) */
10/* so that the byte 3 and word 7 is "connected" */
11/* Your code here. (1/6) */
12.align 0
13.word 7, 8, 9
14
15.text
16/* We define '_start_mips' here as the entry of our program. */
17EXPORT(_start_mips)
18.set at
19.set reorder
20 mtc0 zero, CP0_STATUS
21 li sp, 0x84000000
22 /* Load the address of the string 'str' into the first parameter register. */
23 la a0, str
24 /* use 'addiu sp, sp, <x>' to push a proper-sized frame onto the stack for Nonleaf function 'print_str'. */
25 /* Your code here. (2/6) */
26 addiu sp,sp,-16
27 jal print_str
28 /* use 'addiu sp, sp, <x>' to restore stack pointer. */
29 /* Your code here. (3/6) */
30 addiu sp,sp,16
31 /* Set the first four parameters. */
32 li a0, 0
33 li a1, 1
34 li a2, 2
35 li a3, 3
36 /* use 'addiu sp, sp, <x>' to push a proper-sized frame onto the stack for Nonleaf function 'hello'. */
37 /* Your code here. (4/6) */
38 addiu sp,sp,-24
39 lw t1, var
40 li t2, 5
41 /* use 'sw t1, <x>(sp)' to store t1 at the proper place of the stack */
42 /* so that t1 is 5th argument of function hello. */
43 /* Your code here. (5/6) */
44 sw t1,16(sp)
45 /* use 'sw t2, <x>(sp)' to store t2 at the proper place of the stack */
46 /* so that t2 is 6th argument of function hello. */
47 /* Your code here. (6/6) */
48 sw t2,20(sp)
49 /* use 'j' to call the function 'hello', we use 'j' instead of 'jal' because 'hello' is 'noreturn' */
50 j hello