编译与虚拟机技术入门
“技多不压身”。内卷时代对编译和虚拟机技术有所了解是极好的。可是JVM太庞大了。
这个 虽然只有10KB,但它包含玩具级C编译器和x86虚拟机,阅读它可以快速入门,当然门楣很高:-)。
它是 基本能看懂的C编译器 的改进版,混合使用了自顶向下和自底向上(bison)分析。
① 你可以为它增加do语句等功能。
② 你可以为虚拟机增加指令。可写个t.c,main里return 0;再gcc -m32 -S t.c得到t.s,在里面写汇编指令,再
gcc -m32 -g t.s; gdb a.out; b main; run; disas /r; help disas. With a /r modifier, raw instructions in hex are included.
③ 你可以用Verilog实现虚拟机。Icarus Verilog is a Verilog simulation and synthesis tool. It operates as a compiler, compiling source code into some target format. The compiler can generate an intermediate form called vvp assembly. This intermediate form is executed by the `vvp' command.
④ .com可执行文件不分段,code从0x100开始。生成16位代码的.com,在DOSBox里运行。可以做点图形程序,画圆画线去毛刺等。
⑤ .iso文件的引导记录是啥格式?可以生成个bootable iso,用VirtualBox加载下。INT 13H能用吗?可以做个fdisk, BASIC解释器等。
⑥ Tiny C Compiler生成ELF可执行文件。读懂它起码可以明白ELF格式。
$ sudo apt-get install bison # bison一般默认已有 $ make g++ -g -c -o toyc.o toyc.cpp bison -d -o expr.cpp expr.y g++ -g -c -o expr.o expr.cpp g++ -o toyc toyc.o expr.o g++ -g -c -o toyvm.o toyvm.cpp g++ toyvm.o -o toyvm $ toyc 1.c 生成code.bin和data.bin $ toyvm # 装入code.bin和data.bin并执行之 $ objdump -b binary -m i386 -D code.bin # 查看汇编 ---------------- 源码片段 ------------- void do_block(uint* plevel) { uint pos, p2, p3, tt; if (tk == T_IF) { next_must_be_and_next('('); pos = do_test_expr(); curr_must_be_and_next(')'); do_block(plevel); if (tk == T_ELSE) { yylex(); p2 = gen_jmp(0); patch_jmp(pos); do_block(plevel); patch_jmp(p2); } else patch_jmp(pos); } void do_expr() { reuse_curr_tk = 1; expr::parse(); claim(tk == ',' || tk == ';' || tk == ')'); int n = expr::code.size(); memcpy(code + codetail, expr::code.c_str(), n), codetail += n; } uint do_test_expr() { do_expr(); return gen_je_or_jne(0, 0); } %% start : expr { code = $1; } expr : T_NUM { $$ = load_imm(tkval); } | '"' { $$ = load_imm(tkval); } // such as 0x6804, address of "string" | symbol { $$ = $1; } | '(' expr ')' { $$ = $2; } | '*' '(' T_CHAR '*' ')' expr { $$ = $6 + movsb_eax; } | '-' expr { $$ = $2 + neg_eax; } | expr '+' expr { $$ = $1 + push_eax + $3 + pop_ecx + add_ecx_eax; } | expr '>' expr { $$ = $1 + push_eax + $3 + pop_ecx + cmp_and_set(setg); } | expr T_OR expr { $$ = logical_and_or($1, $3, true); } symbol : T_SYMBOL { $$ = load_local(symbols[tkval]); } /* 2 || 3 10: b8 02 00 00 00 mov $0x2,%eax # x 15: 85 c0 test %eax,%eax 17: 0f 85 17 00 00 00 jne 0x34 # j 1d: b8 03 00 00 00 mov $0x3,%eax # y 22: 85 c0 test %eax,%eax 24: 0f 85 0a 00 00 00 jne 0x34 # j 2a: b8 00 00 00 00 mov $0x0,%eax # t(ail) 2f: e9 05 00 00 00 jmp 0x39 # jmp_5 34: b8 01 00 00 00 mov $0x1,%eax */ str logical_and_or(const str& a, const str& b, bool or_) { str t = load_imm(or_ ? 0 : 1) + jmp_5 + load_imm(or_ ? 1 : 0); str j = or_ ? jne : je; str y = b + test_eax_eax + j + n2s(t.size() - 5) + t; str x = a + test_eax_eax + j + n2s(y.size() - 5); return x + y; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
2022-01-07 RISC-V好像挺靠谱的
2022-01-07 嵌入式名词解释
2022-01-07 What is std::atomic and how to use it?
2022-01-07 A Child's History of England.102