From 14ba7c0fd38c50f5da4ae424b33b750b3bb4593e Mon Sep 17 00:00:00 2001 From: Du Qirong <3577669408@qq.com> Date: Mon, 11 Mar 2024 23:25:22 +0800 Subject: [PATCH 1/8] Add files via upload --- .blib.c.swp | Bin 0 -> 12288 bytes .gitignore | 3 ++ Makefile | 46 +++++++++++++++++ blib.c | 142 ++++++++++++++++++++++++++++++++++++++++++++++++++++ linker.lds | 25 +++++++++ machine.c | 21 ++++++++ start.S | 11 ++++ test.c | 65 ++++++++++++++++++++++++ 8 files changed, 313 insertions(+) create mode 100644 .blib.c.swp create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 blib.c create mode 100644 linker.lds create mode 100644 machine.c create mode 100644 start.S create mode 100644 test.c diff --git a/.blib.c.swp b/.blib.c.swp new file mode 100644 index 0000000000000000000000000000000000000000..1e277a1f2896546062b47d6c3cd8cf637d1017b0 GIT binary patch literal 12288 zcmeI2O^6&t6vr!G%$g5n_u{d#flYtxW@maKS(vORgM>scaf6~^o$2Y>Eu5)sx_fp_ zWX;i&$ArL±TiD2NE2RPdk@l1mPrJP8IP@uCv)e^u4p(=)rXms~=s;kVOO_3G8D zf4zDz%(iM5&b-VQj|U9TbBulW&+W+f19o#iW2+*g-aVfnSU9<`a6-8lXZ#)<&gaJS zt*&St569WtF{^-8;1Ma%&pLC9hn5$DdW}3Doj$^+CYK+PbL++`U=^?mSOu&CRspMk zRlq7>6?hyJ$l`tM3Ict~1e<>$-)GwS=i{&!8>3agDqt0`3RnfK0#*U5fK|XMU=^?m zSOu&CJ1fv^GdB4&W8dKSe)|1C|NejXS;qbZKZCEpHuwO%4=#aCumR436X1Dp7(6)4 z*#F=^@ICk(TmxHR6Li1@@G3YDroq3582ba<0k^<)a1C4q7r|Lj2UB1I+&jqFZ{QaA z0elU<0H16|f3C847G|Z844~iL(B{Ya)5Ap$7CYnZ$M9pXG7j`+9`>%28^O z6U_ADI-kSeptKVm?ojuUCF*ziyNv8N*F-nsj+~pzd%|^@X1p&`u_~iB57(NBa<|0O z`YcW5c!OUdGv14OVJ~*{l#O-K<{lYU+QBSO#pP%v-h~(YKCM#G(G9iPsOS|lh>WRlS;Un_nTac% z*h3cOPlnCR#ESG8lmx@cpx%YsVqu&X<_yF(*45}O7`f+Z<%XxY^`&;D{G?EH&YiL3*flI=eO^oaTZiddDW{lLWBr-SN)3t`u zQ>$2pNJFX!Q2va>h9ZQ}2J5cMY&h20q;ITAO_U|A=^m-Mdz^H*IzXe2GZdcdGP2Rj z>=Xsn#@&M$l}J?eK$UL5zgk3v;G|UL2d*|PU(`W5AHg97?uM!QIJ<5ntCwCadsN7< P+iyqwl=|=cwHMe!&O}g7 literal 0 HcmV?d00001 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..360cd8e --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.vscode +*.o +runbin diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..58d26f9 --- /dev/null +++ b/Makefile @@ -0,0 +1,46 @@ +ENDIAN := EL + +QEMU := qemu-system-mipsel +CROSS_COMPILE := mips-linux-gnu- +CC := $(CROSS_COMPILE)gcc +CFLAGS += --std=gnu99 -$(ENDIAN) -G 0 -mno-abicalls -fno-pic \ + -ffreestanding -fno-stack-protector -fno-builtin \ + -Wa,-xgot -Wall -mxgot -mno-fix-r4000 -march=4kc -g -ggdb +LD := $(CROSS_COMPILE)ld +LDFLAGS += -$(ENDIAN) -G 0 -static -n -nostdlib --fatal-warnings +INCLUDES := -I./include + +qemu_flags += -cpu 4Kc -m 64 -nographic -M malta -no-reboot + +qemu_files += $(target) + +link_script := linker.lds +target := runbin + +objs := blib.o machine.o start.o test.o + +all: $(objs) + $(LD) $(LDFLAGS) -o $(target) -N -T $(link_script) $(objs) + +%.o: %.c + $(CC) $(CFLAGS) $(INCLUDES) -c $< + +%.o: %.S + $(CC) $(CFLAGS) $(INCLUDES) -c $< + +dbg_run: qemu_flags += -s -S +dbg_run: run + +dbg: + make dbg_run >/dev/null 2>&1 & + gdb-multiarch $(target) -ex "target remote localhost:1234" + killall $(QEMU) + +run: + $(QEMU) $(qemu_flags) -kernel $(qemu_files) + +clean: + rm -f *.o $(target) + +.PHONY: all clean run + diff --git a/blib.c b/blib.c new file mode 100644 index 0000000..40592fe --- /dev/null +++ b/blib.c @@ -0,0 +1,142 @@ +#include + +size_t strlen(const char *s) { + size_t i = 0; + while(s[i] != '\0') { + i++; + } + return i; +} + +char *strcpy(char *dst, const char *src) { + char *res = dst; + while ((*dst++ = *src++)) + ; + return res; +} + +char *strncpy(char *dst, const char *src, size_t n) { + char *res = dst; + while (*src && n--) { + *dst++ = *src++; + } + *dst = '\0'; + return res; +} + +int strcmp(const char *str1, const char *str2) { + while (*str1 && (*str1 == *str2)) { + str1++; + str2++; + } + return *(unsigned char *)str1 - *(unsigned char *)str2; +} + +int strncmp(const char *s1, const char *s2, size_t n) { + while (n--) { + if (*s1 != *s2) { + return *s1 - *s2; + } + if (*s1 == 0) { + break; + } + s1++; + s2++; + } + return 0; +} + +char *strcat(char *dst, const char *src) { + char *temp = dst; + while(*temp != '\0'){ + temp++; + } + while(*src != '\0'){ + *temp = *src; + temp++; + src++; + } + *temp = '\0'; + return dst; +} + +char *strncat(char *dst, const char *src, size_t n){ + size_t oplength = n; + if(strlen(src) < n) { + oplength = strlen(src); + } + char * temp = dst; + while(*temp != '\0') { + temp++; + } + for(size_t i = 0;i < oplength;i++) { + *temp++ = *src++; + } + *temp = '\0'; + return dst; +} + +char *strchr(const char *str, int character){ + while (*str != '\0') { + if (*str == (char)character) { + return (char *)str; + } + str++; + } + + return NULL; +} + +char* strsep(char** stringp, const char* delim){ + char *temp = *stringp; + char *preStringp = *stringp; + if(temp == NULL) { + return NULL; + } else { + while(*temp != '\0') { + const char* delete = delim; + while(*delete != '\0') { + if(*delete == *temp) { + *temp = '\0'; + *stringp = temp + 1; + return preStringp; + } + delete++; + } + temp++; + } + if(*temp == '\0'){ + *stringp = NULL; + } + return preStringp; + } +} + + +void *memset(void *s, int c, size_t n) { + unsigned char *p = s; + while (n--) { + *p++ = (unsigned char)c; + } + return s; +} + +void *memcpy(void *out, const void *in, size_t n) { + char *csrc = (char *)in; + char *cdst = (char *)out; + for (size_t i = 0; i < n; i++) { + cdst[i] = csrc[i]; + } + return out; +} + +int memcmp(const void *s1, const void *s2, size_t n) { + const unsigned char *p1 = s1, *p2 = s2; + while (n--) { + if (*p1 != *p2) { + return *p1 - *p2; + } + p1++, p2++; + } + return 0; +} diff --git a/linker.lds b/linker.lds new file mode 100644 index 0000000..577e97e --- /dev/null +++ b/linker.lds @@ -0,0 +1,25 @@ +/* + * Set the architecture to mips. + */ +OUTPUT_ARCH(mips) + +/* + * Set the ENTRY point of the program to _start. + */ +ENTRY(_start) + +SECTIONS { + . = 0x80020000; + + .text : { + *(.text) + } + + .data : { + *(.data) + } + + .bss : { + *(.bss) + } +} diff --git a/machine.c b/machine.c new file mode 100644 index 0000000..6c256c1 --- /dev/null +++ b/machine.c @@ -0,0 +1,21 @@ +#include +#include + +void m_putch(char ch) { + *((volatile char *)(KSEG1 + MALTA_SERIAL_DATA)) = ch; +} + +char m_getch(void) { + if (*((volatile char *)(KSEG1 + MALTA_SERIAL_LSR)) & MALTA_SERIAL_DATA_READY) { + return *((volatile char *)(KSEG1 + MALTA_SERIAL_DATA)); + } + return 0; +} + +void m_halt(void) { + *(char *)(KSEG1 + MALTA_FPGA_HALT) = 0x42; + putstr("machine.c:\thalt is not supported in this machine!\n"); + while (1) { + ; + } +} diff --git a/start.S b/start.S new file mode 100644 index 0000000..a59dd37 --- /dev/null +++ b/start.S @@ -0,0 +1,11 @@ +#include + +.text +EXPORT(_start) +.set at +.set reorder + + mtc0 zero, CP0_STATUS + li sp, 0x80400000 + jal main + j m_halt diff --git a/test.c b/test.c new file mode 100644 index 0000000..876a336 --- /dev/null +++ b/test.c @@ -0,0 +1,65 @@ +#include + +char str[] = "324234+sdfsd+-dsfsffsd/sdfsd*/sdfsdfsdf*3224324///"; +const char *sarray[] = { + "324234", + "sdfsd", + "", + "dsfsffsd", + "sdfsd", + "", + "sdfsdfsdf", + "3224324", + "", + "", + "" + }; + +int main() { + putstr("begin check string\n"); + + panic_on((strlen(str) != 50), "check failed at"); + panic_on((strlen(sarray[2]) != 0), "check failed at"); + + char destination[20] = "Hello, "; + const char *source = "World!"; + char *s = strcat(destination,source); + panic_on((strcmp(s,"Hello, World!") != 0),"check failed at"); + panic_on((strcmp(destination,"Hello, World!") != 0),"check failed at"); + + char destination2[20] = "Hello, "; + const char *source2 = "World!World!World!"; + s = strncat(destination2,source2,6); + panic_on((strcmp(s,"Hello, World!") != 0),"check failed at"); + panic_on((strcmp(destination2,"Hello, World!") != 0),"check failed at"); + + char destination3[20] = "Hello, "; + const char *source3 = "World!"; + s = strncat(destination3,source3,200); + panic_on((strcmp(s,"Hello, World!") != 0),"check failed at"); + panic_on((strcmp(destination3,"Hello, World!") != 0),"check failed at"); + + char destination4[20] = "Hello, "; + const char *source4 = "World!"; + s = strncat(destination4,source4,0); + panic_on((strcmp(s,"Hello, ") != 0),"check failed at"); + panic_on((strcmp(destination4,"Hello, ") != 0),"check failed at"); + + char destination5[20] = ""; + const char *source5 = "Hello World!"; + s = strncat(destination5,source5,12); + panic_on((strcmp(s,"Hello World!") != 0),"check failed at"); + panic_on((strcmp(destination5,"Hello World!") != 0),"check failed at"); + + + char *token; + char *rest = str; + const char *delimiters = "+-*/"; + int index = 0; + while ((token = strsep(&rest, delimiters)) != NULL) { + panic_on((strcmp(sarray[index++],token) != 0), "check failed at"); + } + + putstr("string test pass!\n"); + return 0; +} From e10f857c7787084937e9843cf91433b633a31590 Mon Sep 17 00:00:00 2001 From: Du Qirong <3577669408@qq.com> Date: Mon, 11 Mar 2024 23:26:05 +0800 Subject: [PATCH 2/8] Create README.md --- include/README.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 include/README.md diff --git a/include/README.md b/include/README.md new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/include/README.md @@ -0,0 +1 @@ + From 19a4e7868843e3f85443fd4e0e849c493f307803 Mon Sep 17 00:00:00 2001 From: Du Qirong <3577669408@qq.com> Date: Mon, 11 Mar 2024 23:26:24 +0800 Subject: [PATCH 3/8] Add files via upload --- include/blib.h | 24 +++++++++++++++++++ include/blib_macros.h | 28 ++++++++++++++++++++++ include/machine.h | 55 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 107 insertions(+) create mode 100644 include/blib.h create mode 100644 include/blib_macros.h create mode 100644 include/machine.h diff --git a/include/blib.h b/include/blib.h new file mode 100644 index 0000000..1fd866f --- /dev/null +++ b/include/blib.h @@ -0,0 +1,24 @@ +#ifndef _BLIB_H +#define _BLIB_H + +#include +#include + +typedef unsigned int size_t; +#define NULL 0 + + +size_t strlen(const char *s); +char *strcpy(char *dst, const char *src); +char *strncpy(char *dst, const char *src, size_t n); +char *strcat(char *dst, const char *src); +char *strncat(char *dest, const char *src, size_t n); +int strcmp(const char *s1, const char *s2); +int strncmp(const char *s1, const char *s2, size_t n); +char *strchr(const char *str, int character); +char* strsep(char** stringp, const char* delim); +void *memset(void *s, int c, size_t n); +void *memcpy(void *dst, const void *src, size_t n); +int memcmp(const void *s1, const void *s2, size_t n); + +#endif diff --git a/include/blib_macros.h b/include/blib_macros.h new file mode 100644 index 0000000..3c082c0 --- /dev/null +++ b/include/blib_macros.h @@ -0,0 +1,28 @@ +#ifndef _BLIB_MACROS_H__ +#define _BLIB_MACROS_H__ + +#define STRINGIFY(s) #s +#define TOSTRING(s) STRINGIFY(s) + +#define putstr(s) \ + ({ \ + for (const char *p = s; *p; p++) \ + m_putch(*p); \ + }) + + + +#define panic_on(cond, s) \ + ({ \ + if (cond) { \ + putstr("panic: "); \ + putstr(s); \ + putstr(" @ " __FILE__ ":" TOSTRING(__LINE__) " \n"); \ + m_halt(); \ + } \ + }) + +#define panic(s) panic_on(1, s) + + +#endif /* _printk_h_ */ diff --git a/include/machine.h b/include/machine.h new file mode 100644 index 0000000..56c2120 --- /dev/null +++ b/include/machine.h @@ -0,0 +1,55 @@ +#ifndef _MACHINE_H +#define _MACHINE_H + +// Memory segments (32-bit kernel mode addresses) +#define KUSEG 0x00000000U +#define KSEG0 0x80000000U +#define KSEG1 0xA0000000U +#define KSEG2 0xC0000000U + +/* + * QEMU MMIO address definitions. + */ +#define MALTA_PCIIO_BASE 0x18000000 +#define MALTA_FPGA_BASE 0x1f000000 + +/* + * 16550 Serial UART device definitions. + */ +#define MALTA_SERIAL_BASE (MALTA_PCIIO_BASE + 0x3f8) +#define MALTA_SERIAL_DATA (MALTA_SERIAL_BASE + 0x0) +#define MALTA_SERIAL_LSR (MALTA_SERIAL_BASE + 0x5) +#define MALTA_SERIAL_DATA_READY 0x1 + +/* + * Intel PIIX4 IDE Controller device definitions. + * Hardware documentation available at + * https://www.intel.com/Assets/PDF/datasheet/290562.pdf + */ +#define MALTA_IDE_BASE (MALTA_PCIIO_BASE + 0x01f0) +#define MALTA_IDE_DATA (MALTA_IDE_BASE + 0x00) +#define MALTA_IDE_ERR (MALTA_IDE_BASE + 0x01) +#define MALTA_IDE_NSECT (MALTA_IDE_BASE + 0x02) +#define MALTA_IDE_LBAL (MALTA_IDE_BASE + 0x03) +#define MALTA_IDE_LBAM (MALTA_IDE_BASE + 0x04) +#define MALTA_IDE_LBAH (MALTA_IDE_BASE + 0x05) +#define MALTA_IDE_DEVICE (MALTA_IDE_BASE + 0x06) +#define MALTA_IDE_STATUS (MALTA_IDE_BASE + 0x07) +#define MALTA_IDE_LBA 0xE0 +#define MALTA_IDE_BUSY 0x80 +#define MALTA_IDE_CMD_PIO_READ 0x20 /* Read sectors with retry */ +#define MALTA_IDE_CMD_PIO_WRITE 0x30 /* write sectors with retry */ + +/* + * MALTA Power Management device definitions. + */ +#define MALTA_FPGA_HALT (MALTA_FPGA_BASE + 0x500) + + +/* IO function */ +void m_putch(char ch); +char m_getch(void); +/* when call this func, gxemul will quit */ +void m_halt(void); + +#endif From f3ce4889d7df2b318bdd11c2af780aa40d886877 Mon Sep 17 00:00:00 2001 From: Du Qirong <3577669408@qq.com> Date: Mon, 11 Mar 2024 23:27:32 +0800 Subject: [PATCH 4/8] Create README.md --- include/asm/README.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 include/asm/README.md diff --git a/include/asm/README.md b/include/asm/README.md new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/include/asm/README.md @@ -0,0 +1 @@ + From 061f1fa57f45e21adc48a9ef28ce74a50b23c2c1 Mon Sep 17 00:00:00 2001 From: Du Qirong <3577669408@qq.com> Date: Mon, 11 Mar 2024 23:27:51 +0800 Subject: [PATCH 5/8] Add files via upload --- include/asm/asm.h | 41 ++++++++++++++++++++++++++++++++ include/asm/cp0regdef.h | 52 +++++++++++++++++++++++++++++++++++++++++ include/asm/regdef.h | 43 ++++++++++++++++++++++++++++++++++ 3 files changed, 136 insertions(+) create mode 100644 include/asm/asm.h create mode 100644 include/asm/cp0regdef.h create mode 100644 include/asm/regdef.h diff --git a/include/asm/asm.h b/include/asm/asm.h new file mode 100644 index 0000000..90480f2 --- /dev/null +++ b/include/asm/asm.h @@ -0,0 +1,41 @@ +#include +#include + +/* + * LEAF - declare leaf routine + */ +#define LEAF(symbol) \ + .globl symbol; \ + .align 2; \ + .type symbol, @function; \ + .ent symbol; \ + symbol: \ + .frame sp, 0, ra + +/* + * NESTED - declare nested routine entry point + */ +#define NESTED(symbol, framesize, rpc) \ + .globl symbol; \ + .align 2; \ + .type symbol, @function; \ + .ent symbol; \ + symbol: \ + .frame sp, framesize, rpc + +/* + * END - mark end of function + */ +#define END(function) \ + .end function; \ + .size function, .- function + +#define EXPORT(symbol) \ + .globl symbol; \ + symbol: + +#define FEXPORT(symbol) \ + .globl symbol; \ + .type symbol, @function; \ + symbol: + diff --git a/include/asm/cp0regdef.h b/include/asm/cp0regdef.h new file mode 100644 index 0000000..2000dff --- /dev/null +++ b/include/asm/cp0regdef.h @@ -0,0 +1,52 @@ +#ifndef _cp0regdef_h_ +#define _cp0regdef_h_ + +#define CP0_INDEX $0 +#define CP0_RANDOM $1 +#define CP0_ENTRYLO0 $2 +#define CP0_ENTRYLO1 $3 +#define CP0_CONTEXT $4 +#define CP0_PAGEMASK $5 +#define CP0_WIRED $6 +#define CP0_BADVADDR $8 +#define CP0_COUNT $9 +#define CP0_ENTRYHI $10 +#define CP0_COMPARE $11 +#define CP0_STATUS $12 +#define CP0_CAUSE $13 +#define CP0_EPC $14 +#define CP0_PRID $15 +#define CP0_EBASE $15, 1 +#define CP0_CONFIG $16 +#define CP0_LLADDR $17 +#define CP0_WATCHLO $18 +#define CP0_WATCHHI $19 +#define CP0_XCONTEXT $20 +#define CP0_FRAMEMASK $21 +#define CP0_DIAGNOSTIC $22 +#define CP0_PERFORMANCE $25 +#define CP0_ECC $26 +#define CP0_CACHEERR $27 +#define CP0_TAGLO $28 +#define CP0_TAGHI $29 +#define CP0_ERROREPC $30 + +#define STATUS_CU3 0x80000000 +#define STATUS_CU2 0x40000000 +#define STATUS_CU1 0x20000000 +#define STATUS_CU0 0x10000000 +#define STATUS_BEV 0x00400000 +#define STATUS_IM0 0x0100 +#define STATUS_IM1 0x0200 +#define STATUS_IM2 0x0400 +#define STATUS_IM3 0x0800 +#define STATUS_IM4 0x1000 +#define STATUS_IM5 0x2000 +#define STATUS_IM6 0x4000 +#define STATUS_IM7 0x8000 +#define STATUS_UM 0x0010 +#define STATUS_R0 0x0008 +#define STATUS_ERL 0x0004 +#define STATUS_EXL 0x0002 +#define STATUS_IE 0x0001 +#endif diff --git a/include/asm/regdef.h b/include/asm/regdef.h new file mode 100644 index 0000000..2b73ed2 --- /dev/null +++ b/include/asm/regdef.h @@ -0,0 +1,43 @@ +#ifndef __ASM_MIPS_REGDEF_H +#define __ASM_MIPS_REGDEF_H + +/* + * Symbolic register names for 32 bit ABI + */ +#define zero $0 /* wired zero */ +#define AT $1 /* assembler temp - uppercase because of ".set at" */ +#define v0 $2 /* return value */ +#define v1 $3 +#define a0 $4 /* argument registers */ +#define a1 $5 +#define a2 $6 +#define a3 $7 +#define t0 $8 /* caller saved */ +#define t1 $9 +#define t2 $10 +#define t3 $11 +#define t4 $12 +#define t5 $13 +#define t6 $14 +#define t7 $15 +#define s0 $16 /* callee saved */ +#define s1 $17 +#define s2 $18 +#define s3 $19 +#define s4 $20 +#define s5 $21 +#define s6 $22 +#define s7 $23 +#define t8 $24 /* caller saved */ +#define t9 $25 +#define jp $25 /* PIC jump register */ +#define k0 $26 /* kernel scratch */ +#define k1 $27 +#define gp $28 /* global pointer */ +#define sp $29 /* stack pointer */ +#define fp $30 /* frame pointer */ +#define s8 $30 /* same like fp! */ +#define ra $31 /* return address */ + +#endif /* __ASM_MIPS_REGDEF_H */ + From 9d71c33f5862f52ccff7e7de7e37698ff81f0272 Mon Sep 17 00:00:00 2001 From: Du Qirong <3577669408@qq.com> Date: Mon, 11 Mar 2024 23:28:08 +0800 Subject: [PATCH 6/8] Delete include/README.md --- include/README.md | 1 - 1 file changed, 1 deletion(-) delete mode 100644 include/README.md diff --git a/include/README.md b/include/README.md deleted file mode 100644 index 8b13789..0000000 --- a/include/README.md +++ /dev/null @@ -1 +0,0 @@ - From f3f74e9311f82b2c330418b89d8ee4fdfc0ee746 Mon Sep 17 00:00:00 2001 From: Du Qirong <3577669408@qq.com> Date: Mon, 11 Mar 2024 23:28:35 +0800 Subject: [PATCH 7/8] Delete include/asm/README.md --- include/asm/README.md | 1 - 1 file changed, 1 deletion(-) delete mode 100644 include/asm/README.md diff --git a/include/asm/README.md b/include/asm/README.md deleted file mode 100644 index 8b13789..0000000 --- a/include/asm/README.md +++ /dev/null @@ -1 +0,0 @@ - From 4d077fe9bc39ad4aa3d37513603000f28344a8c9 Mon Sep 17 00:00:00 2001 From: Du Qirong <3577669408@qq.com> Date: Mon, 11 Mar 2024 23:29:12 +0800 Subject: [PATCH 8/8] Delete README.md --- README.md | 1 - 1 file changed, 1 deletion(-) delete mode 100644 README.md diff --git a/README.md b/README.md deleted file mode 100644 index 6b6b764..0000000 --- a/README.md +++ /dev/null @@ -1 +0,0 @@ -2024春季北航操作系统课程代码,不同实验位于不同分支下,谨慎参考!