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
|