-
Notifications
You must be signed in to change notification settings - Fork 0
/
assembly.ml
186 lines (170 loc) · 4.38 KB
/
assembly.ml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
open Printf
(* Abstract syntax of (a small subset of) x86 assembly instructions *)
let word_size = 8
;;
type reg =
| RAX
| RSP
| RBP
| RSI
| RDI
| RDX
| RCX
| R8
| R9
| R10
| R11
| R12
| R13
| R14
| R15
| RBX
| CL
type size =
| QWORD_PTR
| DWORD_PTR
| WORD_PTR
| BYTE_PTR
type arg =
| Const of int64
| HexConst of int64
| Reg of reg
| RegOffset of int * reg (* int is # words of offset *)
| RegOffsetReg of reg * reg * int * int
| Sized of size * arg
| LabelContents of string
| Label of string
type instruction =
| IMov of arg * arg
| IAdd of arg * arg
| ISub of arg * arg
| IMul of arg * arg
| IShl of arg * arg
| IShr of arg * arg
| ISar of arg * arg
| IAnd of arg * arg
| IOr of arg * arg
| IXor of arg * arg
| ILabel of string
| IPush of arg
| IPop of arg
| ICall of arg
| IRet
| ICmp of arg * arg
| ITest of arg * arg
| IJo of arg
| IJno of arg
| IJe of arg
| IJne of arg
| IJl of arg
| IJle of arg
| IJg of arg
| IJge of arg
| IJmp of arg
| IJz of arg
| IJnz of arg
| ILineComment of string
| IInstrComment of instruction * string
let r_to_asm (r : reg) : string =
match r with
| RAX -> "RAX"
| RSI -> "RSI"
| RDI -> "RDI"
| RCX -> "RCX"
| RDX -> "RDX"
| RSP -> "RSP"
| RBP -> "RBP"
| R8 -> "R8"
| R9 -> "R9"
| R10 -> "R10"
| R11 -> "R11"
| R12 -> "R12"
| R13 -> "R13"
| R14 -> "R14"
| R15 -> "R15"
| RBX -> "RBX"
| CL -> "CL"
let rec arg_to_asm (a : arg) : string =
match a with
| Const(n) -> sprintf "%Ld" n
| HexConst(n) -> sprintf "0x%Lx" n
| Reg(r) -> r_to_asm r
| RegOffset(n, r) ->
if n >= 0 then
sprintf "[%s+%d]" (r_to_asm r) n
else
sprintf "[%s-%d]" (r_to_asm r) (-1 * n)
| RegOffsetReg(r1, r2, mul, off) ->
sprintf "[%s + %s * %d + %d]"
(r_to_asm r1) (r_to_asm r2) mul off
| Sized(size, a) ->
sprintf "%s %s"
(match size with | QWORD_PTR -> "QWORD" | DWORD_PTR -> "DWORD" | WORD_PTR -> "WORD" | BYTE_PTR -> "BYTE")
(arg_to_asm a)
| LabelContents s -> sprintf "[%s]" s
| Label s -> s
;;
let rec i_to_asm (i : instruction) : string =
match i with
| IMov(dest, value) ->
sprintf " mov %s, %s" (arg_to_asm dest) (arg_to_asm value)
| IAdd(dest, to_add) ->
sprintf " add %s, %s" (arg_to_asm dest) (arg_to_asm to_add)
| ISub(dest, to_sub) ->
sprintf " sub %s, %s" (arg_to_asm dest) (arg_to_asm to_sub)
| IMul(dest, to_mul) ->
sprintf " imul %s, %s" (arg_to_asm dest) (arg_to_asm to_mul)
| ICmp(left, right) ->
sprintf " cmp %s, %s" (arg_to_asm left) (arg_to_asm right)
| ILabel(name) ->
"align 16\n" ^ name ^ ":"
| IJo(label) ->
sprintf " jo near %s" (arg_to_asm label)
| IJno(label) ->
sprintf " jno near %s" (arg_to_asm label)
| IJe(label) ->
sprintf " je near %s" (arg_to_asm label)
| IJne(label) ->
sprintf " jne near %s" (arg_to_asm label)
| IJl(label) ->
sprintf " jl near %s" (arg_to_asm label)
| IJle(label) ->
sprintf " jle near %s" (arg_to_asm label)
| IJg(label) ->
sprintf " jg near %s" (arg_to_asm label)
| IJge(label) ->
sprintf " jge near %s" (arg_to_asm label)
| IJmp(label) ->
sprintf " jmp near %s" (arg_to_asm label)
| IJz(label) ->
sprintf " jz near %s" (arg_to_asm label)
| IJnz(label) ->
sprintf " jnz near %s" (arg_to_asm label)
| IAnd(dest, value) ->
sprintf " and %s, %s" (arg_to_asm dest) (arg_to_asm value)
| IOr(dest, value) ->
sprintf " or %s, %s" (arg_to_asm dest) (arg_to_asm value)
| IXor(dest, value) ->
sprintf " xor %s, %s" (arg_to_asm dest) (arg_to_asm value)
| IShl(dest, value) ->
sprintf " shl %s, %s" (arg_to_asm dest) (arg_to_asm value)
| IShr(dest, value) ->
sprintf " shr %s, %s" (arg_to_asm dest) (arg_to_asm value)
| ISar(dest, value) ->
sprintf " sar %s, %s" (arg_to_asm dest) (arg_to_asm value)
| IPush(value) ->
sprintf " push %s" (arg_to_asm value)
| IPop(dest) ->
sprintf " pop %s" (arg_to_asm dest)
| ICall(label) ->
sprintf " call %s" (arg_to_asm label)
| IRet ->
" ret"
| ITest(arg, comp) ->
sprintf " test %s, %s" (arg_to_asm arg) (arg_to_asm comp)
| ILineComment(str) ->
sprintf " ;; %s" str
| IInstrComment(instr, str) ->
sprintf "%s ; %s" (i_to_asm instr) str
let to_asm (is : instruction list) : string =
List.fold_left (fun s i -> sprintf "%s\n%s" s (i_to_asm i)) "" is