summaryrefslogtreecommitdiff
path: root/bismuth.asm
blob: b5f6182da5265c5b54b82551382e5025bd5dbe36 (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
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  bismuth ; We want to use our main interpreter, bismuth.
    dd      data
    dd          prog
    dd              data
    dd                  0x0a20202e
    dd                  0x2e2e6948
    dd              quote, eval, 0, pop
    dd          quote, eval, 0
    dd      0, quote, msg, copywords
    dd      data, msg, eval, msg, eval, 0, output
    dd  0


; 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, pop byte from it:
%macro bispopbyte 1
    mov %1, byte [edi]
    inc edi
%endmacro

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

; Top of the stack is in edi, push byte onto it:
%macro bispushbyte 1
    dec edi
    mov byte [edi], %1
%endmacro

; Calling conventions for interpreters:
%macro bisinterpret 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
    bisinterpret 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! =)

bismuth:
    dd bismuth
    mov esi, [ebp+4]
bismuthloop:
    bisnext eax
    cmp eax, 0
    je bismuthend
    bisinterpret eax
    jmp bismuthloop
bismuthend:
    mov [ebp+4], esi
    ret

prog:
    dd prog
progloop:
    bisnext eax
    cmp eax, 0
    je progend
    bisinterpret eax
    jmp progloop
progend:
    ret

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
    mov esi, [ebp+4]
    bispop eax
    bisinterpret eax
    mov [ebp+4], esi
    ret

data:
    dd data
    mov esi, [ebp+4]
    push edi
dataloop:
    bisnext eax
    cmp eax, eval
    je dataeval
    cmp eax, 0
    je dataend
    bispush eax
    jmp dataloop
dataeval:
    bisinterpret eax
    jmp dataloop
dataend:
    pop eax
    sub eax, edi
    bispush eax
    mov [ebp+4], esi
    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