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