summaryrefslogtreecommitdiff
path: root/bismuth.asm
blob: b6a04363c34fba58b6a605f11a1340526cc06ca1 (plain)
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
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
section .data
; This is stack of 4KB:
    db 4096 dup 0
stackbottom:
; Place to copy msg content into:
msg:
    db 1024 dup 0
; And finally our program:
program:
    dd  bismuthint ; We want to use our main interpreter, bismuth.
    dd      top, local, data
    dd          dataint
    dd              0x0a20202e
    dd              0x2e2e6948
    dd          endint, quote, eval, eval,
    dd      end, eval, top, getlocal, sub, quote, msg, copywords
    dd      top, local, msg, msg, top, getlocal, sub, output
    dd  endint


; The input is in esi, pop dword from it:
%macro bisnext 1
    mov %1, dword [esi]
    add esi, 4
%endmacro

; Top of the stack is in edi, pop dword from it:
%macro bispop 1
    mov %1, dword [edi]
    add edi, 4
%endmacro

; Top of the stack is in edi, push dword onto it:
%macro bispush 1
    sub edi, 4
    mov dword [edi], %1
%endmacro

; Calling conventions for interpreters:
%macro biscall 1
    push esi
    mov esi, %1
    bisnext eax
    add eax, 4
    push ebp
    mov ebp, esp
    call eax
    mov esp, ebp
    pop ebp
    pop esi
%endmacro


section .text
global _start
_start:
    mov esi, program        ; We will read and execute program
    mov edi, stackbottom    ; and write results onto stack.
    bisnext eax             ; Read interpreter
    biscall eax             ; and start interpretation.
    ; After execution of program we will exit properly:
    mov ebx, 0              ; We have no error (error code = 0)
    mov eax, 1              ; and we want to exit.
    int 0x80                ; Send this to kernel.
    ; That's all! =)

bismuthint:
    dd bismuthint
    mov esi, [ebp+4]
bismuthloop:
    bisnext eax
    biscall eax
    jmp bismuthloop

pop:
    dd pop
    add edi, 4
    ret

copy:
    dd copy
    mov eax, dword [edi]
    sub edi, 4
    mov dword [edi], eax
    ret

quote:
    dd quote
    mov esi, [ebp+4]
    bisnext eax
    bispush eax
    mov [ebp+4], esi
    ret

eval:
    dd eval
    pop eax
    pop ebp
    pop esi
    bispop ebx
    push esi
    mov esi, ebx
    bisnext ebx
    add ebx, 4
    push ebp
    mov ebp, esp
    push eax
    jmp ebx

data:
    dd data
    mov esi, [ebp+4]
dataloop:
    bisnext eax
    cmp eax, eval
    je dataeval
    bispush eax
    jmp dataloop
dataeval:
    biscall eax
    jmp dataloop

dataint:
    dd dataint
dataintloop:
    bisnext eax
    cmp eax, eval
    je datainteval
    bispush eax
    jmp dataintloop
datainteval:
    biscall eax
    jmp dataloop

end:
    dd end
    mov esp, ebp
    pop ebp
    pop esi
    mov esp, ebp
    sub esp, 4
    mov [ebp+4], esi
    ret

endint:
    dd endint
    mov esp, ebp
    pop ebp
    pop esi
    mov esp, ebp
    sub esp, 4
    ret

copywords:
    dd copywords
    bispop ebx
    bispop ecx
    sub ebx, 4
copywordsloop:
    bispop eax
    mov dword [ebx+ecx], eax
    sub ecx, 4
    jnz copywordsloop
    ret

output:
    dd output
    bispop edx
    mov ecx, edi
    mov ebx, 1
    mov eax, 4
    int 0x80
    add edi, edx
    ret

top:
    dd top
    mov eax, stackbottom
    sub eax, edi
    bispush eax
    ret

local:
    dd local
    pop eax
    pop ebp
    pop esi
    bispop ebx
    push ebx
    push esi
    push ebp
    mov ebp, esp
    push eax
    ret

getlocal:
    dd getlocal
    pop eax
    pop ebp
    pop esi
    pop ebx
    bispush ebx
    push esi
    push ebp
    mov ebp, esp
    push eax
    ret

sub:
    dd sub
    bispop ebx
    bispop eax
    sub eax, ebx
    bispush eax
    ret