Skip to content

Instantly share code, notes, and snippets.

@darkf
Created January 27, 2013 14:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save darkf/4648583 to your computer and use it in GitHub Desktop.
Save darkf/4648583 to your computer and use it in GitHub Desktop.
Stack-based VM in OCaml with comparison x86 program
(* Ugly imperative code, meant to be the start of something else - ideally `iter ()` would become `iter ip`. *)
type value = Int of int
| Str of string
type op = Nop
| Push of value
| Dup
| Mul
| Add
| Jump of value
| JumpLT of value * value
| Call of value
type astack = {mutable values : value list}
let stack = {values=[]}
let push v =
stack.values <- v :: stack.values
let pop () =
match stack.values with
| [] -> failwith "pop on empty stack"
| x::xs ->
stack.values <- xs;
x
let peek () =
match stack.values with
| [] -> failwith "peek on empty stack"
| x::_ -> x
let string_of_value = function
| Int i -> string_of_int i
| Str s -> s
let exec program =
let ip = ref 0 in
let rec iter () =
let op = List.nth program !ip in
(match op with
| Nop -> ()
| Push v -> push v
| Dup -> push (peek ())
| Add ->
(match (pop (), pop ()) with
| (Int rhs, Int lhs) -> push (Int (lhs+rhs))
| (_, _) -> failwith "invalid operands to add")
| Mul ->
(match (pop (), pop ()) with
| (Int rhs, Int lhs) -> push (Int (lhs*rhs))
| (_, _) -> failwith "invalid operands to mul")
| Jump v ->
(match v with
| Int addr ->
ip := addr-1 (* todo: make this more pretty *)
| _ -> failwith "invalid operand to jump")
| JumpLT (a, v) ->
(match (a, v) with
| (Int addr, Int value) ->
(match peek () with
| Int i ->
if i < value then
ip := addr-1
| _ -> failwith "non-int value in JumpLT")
| _ -> failwith "invalid operand to jump")
| Call p ->
(match p with
| Str "print" -> Printf.printf ": %s\n" (string_of_value (pop ()))
| _ -> Printf.printf "todo: call %s\n" (string_of_value p)));
ip := !ip + 1;
if !ip < List.length program then
iter ()
in
iter ()
let () =
let program = [Push (Int 0);
Push (Int 1);
Add;
Dup;
Push (Int 10);
Mul;
Call (Str "print");
JumpLT (Int 1, Int 10)
] in
exec program
# I hate my life, that's why I'm writing x86 assembly with AT&T syntax at 6am on a Sunday using only ideone.com
.data
s: .string "%d\n\0"
.text
.global main
main:
xor %eax,%eax
loop:
movl $1, %ebx
addl %ebx,%eax
pushl %eax # add
movl $10,%ebx
mul %ebx
pushl %eax # mul
pushl $s
call printf
addl $8, %esp
popl %eax # pop add
cmp $10,%eax
jl loop
xor %eax, %eax
ret
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment