-
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathassembler-demo.oak
More file actions
148 lines (119 loc) · 3.66 KB
/
assembler-demo.oak
File metadata and controls
148 lines (119 loc) · 3.66 KB
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
// assembler-demo.oak
// Demonstrates the Magnolia assembler library for x86-64 and ARM64
//
// Shows how to assemble instructions, inspect byte encodings,
// work with labels, and view relocations.
std := import('std')
str := import('str')
fmt := import('fmt')
assembler := import('assembler')
{
println: println
map: map
each: each
keys: keys
} := std
nl := char(10)
// Helper: convert a list of bytes to a hex string like '48 c7 c0 3c'
fn bytesToHex(bytes) {
map(bytes, fn(b) {
hi := std.toHex((b >> 4) & 15)
lo := std.toHex(b & 15)
hi + lo
}) |> str.join(' ')
}
// ============================================================
// 1. Basic x86-64 instructions
// ============================================================
println('=== x86-64 Basic Instructions ===' + nl)
instructions := [
['nop', 'nop']
['ret', 'ret']
['syscall', 'syscall']
['int3', 'int3']
['hlt', 'hlt']
['push rax', 'push rax']
['push rbp', 'push rbp']
['pop rax', 'pop rax']
['xor rdi rdi', 'xor rdi rdi']
]
each(instructions, fn(pair) {
label := pair.0
source := pair.1
result := assembler.assemble(source, :x86_64)
hex := bytesToHex(result.code)
println(fmt.format(' {{0}} => {{1}}', label, hex))
})
println('')
// ============================================================
// 2. x86-64 program: Linux exit(0) syscall
// ============================================================
println('=== x86-64 Program: exit(0) ===' + nl)
exitProgram := str.join([
'_start:'
'xor rdi rdi'
'syscall'
], nl)
exitResult := assembler.assemble(exitProgram, :x86_64)
println(' Source:')
println(' _start:')
println(' xor rdi rdi // exit code 0')
println(' syscall // invoke kernel')
println('')
println(' Machine code: ' + bytesToHex(exitResult.code))
println(' Total bytes: ' + string(len(exitResult.code)))
println(' Labels: _start -> offset ' + string(exitResult.labels._start))
println('')
// ============================================================
// 3. x86-64 labels and jumps
// ============================================================
println('=== x86-64 Labels & Jumps ===' + nl)
jumpProgram := str.join([
'start:'
'xor rax rax'
'jmp done'
'nop'
'done:'
'ret'
], nl)
jumpResult := assembler.assemble(jumpProgram, :x86_64)
println(' Machine code: ' + bytesToHex(jumpResult.code))
println(' Labels:')
each(keys(jumpResult.labels), fn(name) {
println(' ' + name + ' -> byte offset ' + string(jumpResult.labels.(name)))
})
println(' Relocations: ' + string(len(jumpResult.relocations)))
println('')
// ============================================================
// 4. ARM64 basic instructions
// ============================================================
println('=== ARM64 Basic Instructions ===' + nl)
armInstructions := [
['nop', 'nop']
['ret', 'ret']
['add x2 x0 x1', 'add x2 x0 x1']
['sub x3 x1 x0', 'sub x3 x1 x0']
['svc 0', 'svc 0']
]
each(armInstructions, fn(pair) {
label := pair.0
source := pair.1
result := assembler.assemble(source, :arm64)
hex := bytesToHex(result.code)
println(fmt.format(' {{0}} => {{1}} ({{2}} bytes)', label, hex, string(len(result.code))))
})
println('')
// ============================================================
// 5. ARM64 program: Linux exit(0) via svc
// ============================================================
println('=== ARM64 Program: exit(0) ===' + nl)
armExit := str.join([
'_start:'
'svc 0'
], nl)
armResult := assembler.assemble(armExit, :arm64)
println(' Machine code: ' + bytesToHex(armResult.code))
println(' Total bytes: ' + string(len(armResult.code)))
println(' Labels: _start -> offset ' + string(armResult.labels._start))
println('')
println('=== Done ===' + nl)