计算机系统是严格的数学对象:没有魔法;计算机系统的一切行为都是可观测、可理解的。
状态机: 表示有限个状态以及在这些状态之间的转移和动作等行为的数学计算模型
00000040: 4111 06e4 22e0 0008 1705 0000 1305 0500
00000050: 9700 0000 e780 0000 8147 3e85 a260 0264
00000060: 4101 8280
main:
addi sp,sp,-16
sd ra,8(sp)
sd s0,0(sp)
addi s0,sp,16
几乎是简单的替换
几乎是简单的替换
0000000000000000 <main>:
0: 1141 addi sp,sp,-16
2: e406 sd ra,8(sp)
4: e022 sd s0,0(sp)
6: 0800 addi s0,sp,16
8: 00000517 auipc a0,0x0
c: 00050513 mv a0,a0
10: 00000097 auipc ra,0x0
14: 000080e7 jalr ra #10 <main+0x10>
18: 4781 li a5,0
1a: 853e mv a0,a5
1c: 60a2 ld ra,8(sp)
1e: 6402 ld s0,0(sp)
20: 0141 addi sp,sp,16
22: 8082 ret
main.c
-> 汇编语言main.S
gcc ./main.c -S ./main.S
main.S
-> 可执行文件main
gcc ./main.S -o ./main
main
并不只包含了机器语言,还包含了指示系统如何运行这个文件的信息。
while (1) {
从PC指示的存储器位置取出指令;
执行指令;
更新PC;
}
运算器:ALU
控制器:逻辑电路控制器
存储器:内存、寄存器
总线:
冯·诺伊曼体系结构的核心思想
- 使用二进制表示数据
- 程序指令和数据并存
- 计算机的五个基本组成部分
addi x1, x0, 0xf 0x00f00093
定义如下规则:
使用两个异或门和两个与门和一个或门,实现了一个加法器
将之前的电路抽象成一个icon 这样便无需在意里面的具体细节
逐个拼接就能实现32位,乃至64位的加法
将这个电路模型抽象为一个icon
按照这个思路继续抽象,便能得到一个CPU的模型
可执行文件并不只包含了该程序的机器语言,还包含了指示系统如何运行这个文件的信息。
获取代码: https://e1psycongroo.github.io/NekoBytes-TheMissing/_site/resources/Lecture3/Codes/os-exec
#include <sys/syscall.h>
#include <unistd.h>
const char str[] = "\033[01;31mHello, OS World\033[0m\n";
const int str_size = sizeof str - 1;
int main(void) {
asm volatile("movl %0, %%eax\n\t" // 系统调用号:SYS_write
"movl $1, %%edi\n\t" // 文件描述符:STDOUT_FILENO (标准输出)
"movq %2, %%rsi\n\t" // 字符串地址
"movl %3, %%edx\n\t" // 字符串长度
"syscall" // 调用系统调用
:
: "r"(SYS_write), "r"(STDOUT_FILENO), "r"(str), "r"(str_size)
: "eax", "edi", "rsi", "edx");
return 0;
}
获取代码: https://e1psycongroo.github.io/NekoBytes-TheMissing/_site/resources/Lecture3/Codes/stack.c
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int x = 1;
void *y = malloc(sizeof(int));
printf("stack: %p\n", (void *)&x);
printf("heap : %p\n", y);
free(y);
return 0;
}
可能的输出:
stack: 0x7ffd27bb38dc
heap : 0x59e598fe42a0
获取代码: https://e1psycongroo.github.io/NekoBytes-TheMissing/_site/resources/Lecture3/Codes/os-model
enum {
SYS_EXIT, // Process exits
SYS_WRITE, // Write to console with a character
};
typedef struct {
unsigned int syscall;
char arg;
} Syscall;
typedef struct {
int remainingStep; // A process will run remainingStep steps
char charToOutput; // A process will write this character
// to console by doing a syscall
} Process; // Process's Context
void run() {
Process *current;
while (process_count()) {
// The Operating System will randomly
// choose a process to run
current = process_schedule();
// Switch process context and run it until a syscall
Syscall call = process_step(current);
if (call.syscall == SYS_EXIT) {
// Process exits
process_exit(current);
} else if (call.syscall == SYS_WRITE) {
// Write the character from syscall arg to the console
putchar(call.arg);
}
}
putchar('\n');
}
int main() {
// Initialize the Operating System
init();
// spawn processes
spawn_process(5, 'A');
spawn_process(5, 'B');
spawn_process(5, 'C');
// start running
run();
return 0;
}
可能的输出:
AABCCCBBBCBCAAA
BBAACCCABBACCAB
CAAACBCCBBAACBB