Created
January 27, 2013 14:29
-
-
Save darkf/4648583 to your computer and use it in GitHub Desktop.
Stack-based VM in OCaml with comparison x86 program
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(* 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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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