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