3c7f429a9573deace3750cbfe4961eb891e69362
[sped.git] / repl.asm
1
2 %include "fileutils.S"
3
4 extern printf
5 extern fflush
6 extern stdout
7 extern free
8
9 global repl
10
11 section .data
12     prompt_str db `sped > `, 0x00
13     invalidcmd_str db `invalid command\n`, 0x00
14     invalidaddr_str db `invalid address\n`, 0x00
15     charcount_str db `read %i chars\n`, 0x00
16     currentline_str db `current line: %i\n`, 0x00
17     echo_str db `%s`, 0x00 ; print strings without format exploit
18
19 section .bss
20     buffer resb 4
21     buffer_lines resb 4
22     buffer_filename resb 4
23     cur_line resb 4
24
25 section .text
26
27 ; prompt for user
28 ; args: buffer, buffer_lines, buffer_filename
29 repl:
30
31     %define _BUFFER          16
32     %define _BUFFER_LINES    12
33     %define _BUFFER_FILENAME 8
34     %define CMDSTR           4 ; the previous line read from user
35
36     push ebp
37     mov ebp, esp
38
39     sub esp, 4
40     
41     ; set bss vars
42     mov eax, [ebp+_BUFFER]
43     mov [buffer], eax
44     mov eax, [ebp+_BUFFER_LINES]
45     mov [buffer_lines], eax
46     mov eax, [ebp+_BUFFER_FILENAME]
47     mov [buffer_filename], eax
48     mov DWORD [cur_line], 0x00
49
50     _repl_loop:
51     
52     ; print the prompt
53     push prompt_str
54     call printf
55     push DWORD [stdout]
56     call fflush
57
58     ; read line from stdin
59     push 0
60     call readLine
61
62     mov DWORD [ebp-CMDSTR], eax
63
64     ; commands are single char for now
65     cmp ecx, 1 
66     jne _repl_invalid_cmd
67
68     ; parse commands
69     mov eax, DWORD [ebp-CMDSTR]
70     mov eax, [eax]
71
72     ; q exists program =-=-=-=-=-=-=-=-=-=-=-=-=
73     mov eax, DWORD [ebp-CMDSTR]
74     cmp BYTE [eax], 'q'
75     jne _repl_cmd_quit_end
76     jmp _repl_exit
77     _repl_cmd_quit_end:
78
79     ; p prints current line =-=-=-=-=-=-=-=-=-=-=
80     mov eax, DWORD [ebp-CMDSTR]
81     cmp BYTE [eax], 'p'
82     jne _repl_cmd_print_end
83
84     mov eax, DWORD [cur_line]
85     mov ecx, 4
86     mul ecx
87     add eax, [buffer]
88     push DWORD [eax]
89     push echo_str
90     call printf
91     jmp _repl_continue
92     _repl_cmd_print_end:
93
94     ; n prints the current line number =-=-=-=-=-=-=-=
95     mov eax, DWORD [ebp-CMDSTR]
96     cmp BYTE [eax], 'n'
97     jne _repl_cmd_number_end
98
99     push DWORD [cur_line]
100     push currentline_str
101     call printf
102
103     jmp _repl_continue
104     _repl_cmd_number_end:
105
106     ; - goes to prev line =-=-=-=-=-=-=-=-=-=-=-=-=
107     mov eax, DWORD [ebp-CMDSTR]
108     cmp BYTE [eax], '-'
109     jne _repl_cmd_decline_end
110
111     ; make sure we are within bounds
112     mov eax, DWORD [cur_line] 
113     sub eax, 1
114     cmp eax, 0
115     jl _repl_invalid_addr
116     
117     sub DWORD [cur_line], 1
118
119     jmp _repl_continue
120     _repl_cmd_decline_end:
121
122     ; + goes to next line =-=-=-=-=-=-=-=-=-=-=-=-=
123     mov eax, DWORD [ebp-CMDSTR]
124     cmp BYTE [eax], '+'
125     jne _repl_cmd_incline_end
126
127     ; make sure we are within bounds 
128     mov eax, DWORD [cur_line] 
129     add eax, 1
130     cmp eax, [buffer_lines]
131     jge _repl_invalid_addr
132     
133     add DWORD [cur_line], 1
134
135     jmp _repl_continue
136     _repl_cmd_incline_end:
137
138     ; g goes to first line =-=-=-=-=-=-=-=-=-=-=-=-=
139     mov eax, DWORD [ebp-CMDSTR]
140     cmp BYTE [eax], 'g'
141     jne _repl_cmd_jumptop_end
142
143     mov DWORD [cur_line], 0x00
144
145     jmp _repl_continue
146     _repl_cmd_jumptop_end:
147
148     ; G goes to last line =-=-=-=-=-=-=-=-=-=-=-=-=
149     mov eax, DWORD [ebp-CMDSTR]
150     cmp BYTE [eax], 'G'
151     jne _repl_cmd_jumpbot_end
152
153     mov eax, DWORD [buffer_lines]
154     sub eax, 1
155     mov DWORD [cur_line], eax
156
157     jmp _repl_continue
158     _repl_cmd_jumpbot_end:
159
160     ; c changes the current line =-=-=-=-=-=-=-=-=-=
161     mov eax, DWORD [ebp-CMDSTR]
162     cmp BYTE [eax], 'c'
163     jne _repl_cmd_change_end
164
165     ; read a new line to use
166     push 0
167     call readLine
168
169     mov esi, eax
170
171     ; free old string
172     mov eax, [cur_line]
173     mov ecx, 4
174     mul ecx
175     add eax, [buffer]
176     push DWORD [eax]
177     call free
178
179     ; insert new string
180     mov eax, [cur_line]
181     mov ecx, 4
182     mul ecx
183     add eax, DWORD [buffer]
184     mov [eax], esi
185
186     jmp _repl_continue
187     _repl_cmd_change_end:
188
189     ; d delete line =-=-=-=-=-=-=-=-=-=-=-=-=
190     mov eax, DWORD [ebp-CMDSTR]
191     cmp BYTE [eax], 'd'
192     jne _repl_cmd_delete_end
193
194     
195
196     jmp _repl_continue
197     _repl_cmd_delete_end:
198
199     ; w writes file =-=-=-=-=-=-=-=-=-=-=-=-=
200     mov eax, DWORD [ebp-CMDSTR]
201     cmp BYTE [eax], 'w'
202     jne _repl_cmd_write_end
203
204     push DWORD [buffer_filename]
205     push DWORD [buffer]
206     push DWORD [buffer_lines]
207     call writeFile
208
209     jmp _repl_continue
210     _repl_cmd_write_end:
211
212
213     ; if no commands were matched, it's an error
214     jmp _repl_invalid_cmd
215
216     ; some error messages
217     _repl_invalid_cmd:
218     push invalidcmd_str
219     call printf
220     jmp _repl_continue
221
222     _repl_invalid_addr:
223     push invalidaddr_str
224     call printf
225     jmp _repl_continue
226
227     _repl_continue:
228     jmp _repl_loop
229     
230     _repl_exit:
231
232     %undef _BUFFER
233     %undef _BUFFER_LINES
234     %undef _BUFFER_FILENAME
235     %undef CMDSTR
236
237     mov esp, ebp
238     pop ebp
239     ret
240