编译与虚拟机技术入门

“技多不压身”。内卷时代对编译和虚拟机技术有所了解是极好的。可是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;
}
posted @ 2023-01-07 00:08  Fun_with_Words  阅读(56)  评论(0编辑  收藏  举报









 张牌。