An exercise in minimalism.
Try the following:
gcc -o c4 c4.c
./c4 hello.c
./c4 -s hello.c
./c4 c4.c hello.c
./c4 c4.c c4.c hello.c
int *pc, *sp, *bp, a, cycle;
pc
程序计数器/指令指针sp
堆栈寄存器,指向栈顶,栈由高地质向低地址生长bp
基址寄存器a
累加器cycle
执行指令计数
LEA
去局部变量地址, 以[PC+1]
地址, 以bp
为基址, 地址载入累加器a
IMM
[PC+1]
作为为立即数载入累加器a
JMP
无条件跳转到[PC+1]
JSR
进入子程序, 将PC+2
入栈作为返回地址,跳转到[PC+1]
BZ
累加器为零时分支, 当累加器a
为 0 时跳转到[PC+1]
, 不为零时跳转到PC+2
继续执行BNZ
累加器不为零时分支, 当累加器a
不为 0 时跳转到[PC+1]
, 为零时跳转到PC+2
ENT
进入子程序, 将bp
压栈, 基址bp
指向栈顶, 然后将栈顶生长[PC+1]
字, 作为参数传递空间ADJ
LEV
离开子程序, 堆栈指针sp = bp
, 从堆栈中弹出基址bp
,pc
LI
以a
为地址取int数LC
以a
为地址取charSI
以栈顶为地址存int数并弹栈[[sp++]]=a
SC
以栈顶为地址存char并弹栈[[sp++]]=a
PSH
将a
压栈OR
a = [sp++] | a
XOR
a = [sp++] ^ a
AND
a = [sp++] & a
EQ
a = [sp++] == a
NE
a = [sp++] != a
LT
a = [sp++] a
GT
a = [sp++] > a
LE
a = [sp++] <= a
GE
a = [sp++] >= a
SHL
a = [sp++] << a
SHR
a = [sp++] >> a
ADD
a = [sp++] + a
SUB
a = [sp++] - a
MUL
a = [sp++] * a
DIV
a = [sp++] / a
MOD
a = [sp++] % a
OPEN
调用 C 库函数open
, 堆栈传递 2 个参数(第一个参数先进栈, 返回值存入累加器a
, 下同)READ
调用 C 库函数read
, 堆栈传递 2 个参数CLOS
调用 C 库函数close
, 堆栈传递 2 个参数PRTF
调用 C 库函数printf
,[pc+1]
表明参数个数, 传递至多六个参数MALC
调用 C 库函数malloc
, 堆栈传递一个参数MSET
调用 C 库函数memset
, 堆栈传递 3 个参数MCMP
调用 C 库函数memcmp
, 堆栈传递 3 个参数EXIT
打印虚拟机执行情况, 返回[sp]