more commands + readme
[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     cur_line resb 4
37
38 section .text
39 main:
40     %define _ARGC 8
41     %define _ARGV 12
42
43     push ebp
44     mov ebp, esp
45
46     ; read command line args
47     mov ecx, [ebp+_ARGC]
48     cmp ecx, 1
49     jg _main_existing
50     
51     ; display error msg if no file
52     push nofile_str
53     call printf
54     mov eax, 1
55     jmp _main_exit
56
57     _main_existing:
58     mov ebx, DWORD [ebp+_ARGV]
59     add ebx, 4 ; first user arg is filename
60     push DWORD [ebx]
61     call readFile
62
63     mov [buffer], eax
64     mov [buffer_lines], ecx
65     mov DWORD [cur_line], 0x00
66
67     push DWORD [buffer_lines]
68     push readlines_str
69     call printf
70
71     call repl
72
73     mov eax, 0
74     jmp _main_exit
75
76     _main_exit:
77
78     ; free string array
79
80
81     %undef _ARGC
82     %undef _ARGV
83
84     mov esp, ebp
85     pop ebp
86     ret
87
88 ; prompt for user
89 ; no args - reads from globals
90 repl:
91
92     %define CMDSTR 4 ; the previous line read from user
93
94     push ebp
95     mov ebp, esp
96
97     sub esp, 4
98
99     _repl_loop:
100     
101     ; print the prompt
102     push prompt_str
103     call printf
104     push DWORD [stdout]
105     call fflush
106
107     ; read line from stdin
108     push 0
109     call readLine
110
111     mov DWORD [ebp-CMDSTR], eax
112
113     ; commands are single char for now
114     cmp ecx, 1 
115     jne _repl_invalid_cmd
116
117     ; parse commands
118     mov eax, DWORD [ebp-CMDSTR]
119     mov eax, [eax]
120
121     ; q exists program =-=-=-=-=-=-=-=-=-=-=-=-=
122     mov eax, DWORD [ebp-CMDSTR]
123     cmp BYTE [eax], 'q'
124     jne _repl_cmd_quit_end
125     jmp _repl_exit
126     _repl_cmd_quit_end:
127
128     ; p prints current line =-=-=-=-=-=-=-=-=-=-=
129     mov eax, DWORD [ebp-CMDSTR]
130     cmp BYTE [eax], 'p'
131     jne _repl_cmd_print_end
132
133     mov eax, DWORD [cur_line]
134     mov ecx, 4
135     mul ecx
136     add eax, [buffer]
137     push DWORD [eax]
138     push echo_str
139     call printf
140     jmp _repl_continue
141     _repl_cmd_print_end:
142
143     ; n prints the current line number =-=-=-=-=-=-=-=
144     mov eax, DWORD [ebp-CMDSTR]
145     cmp BYTE [eax], 'n'
146     jne _repl_cmd_number_end
147
148     push DWORD [cur_line]
149     push currentline_str
150     call printf
151
152     jmp _repl_continue
153     _repl_cmd_number_end:
154
155     ; - goes to prev line =-=-=-=-=-=-=-=-=-=-=-=-=
156     mov eax, DWORD [ebp-CMDSTR]
157     cmp BYTE [eax], '-'
158     jne _repl_cmd_decline_end
159
160     ; make sure we are within bounds
161     mov eax, DWORD [cur_line] 
162     sub eax, 1
163     cmp eax, 0
164     jl _repl_invalid_addr
165     
166     sub DWORD [cur_line], 1
167
168     jmp _repl_continue
169     _repl_cmd_decline_end:
170
171     ; + goes to next line =-=-=-=-=-=-=-=-=-=-=-=-=
172     mov eax, DWORD [ebp-CMDSTR]
173     cmp BYTE [eax], '+'
174     jne _repl_cmd_incline_end
175
176     ; make sure we are within bounds 
177     mov eax, DWORD [cur_line] 
178     add eax, 1
179     cmp eax, [buffer_lines]
180     jge _repl_invalid_addr
181     
182     add DWORD [cur_line], 1
183
184     jmp _repl_continue
185     _repl_cmd_incline_end:
186
187     ; g goes to first line =-=-=-=-=-=-=-=-=-=-=-=-=
188     mov eax, DWORD [ebp-CMDSTR]
189     cmp BYTE [eax], 'g'
190     jne _repl_cmd_jumptop_end
191
192     mov DWORD [cur_line], 0x00
193
194     jmp _repl_continue
195     _repl_cmd_jumptop_end:
196
197     ; G goes to last line =-=-=-=-=-=-=-=-=-=-=-=-=
198     mov eax, DWORD [ebp-CMDSTR]
199     cmp BYTE [eax], 'G'
200     jne _repl_cmd_jumpbot_end
201
202     mov eax, DWORD [buffer_lines]
203     sub eax, 1
204     mov DWORD [cur_line], eax
205
206     jmp _repl_continue
207     _repl_cmd_jumpbot_end:
208
209     ; c changes the current line =-=-=-=-=-=-=-=-=-=
210     mov eax, DWORD [ebp-CMDSTR]
211     cmp BYTE [eax], 'c'
212     jne _repl_cmd_change_end
213
214     ; read a new line to use
215     push 0
216     call readLine
217
218     mov esi, eax
219
220     ; free old string
221     mov eax, [cur_line]
222     mov ecx, 4
223     mul ecx
224     add eax, [buffer]
225     push DWORD [eax]
226     call free
227
228     ; insert new string
229     mov eax, [cur_line]
230     mov ecx, 4
231     mul ecx
232     add eax, DWORD [buffer]
233     mov [eax], esi
234
235     jmp _repl_continue
236     _repl_cmd_change_end:
237
238
239     jmp _repl_invalid_cmd
240
241     ; some error messages
242     _repl_invalid_cmd:
243     push invalidcmd_str
244     call printf
245     jmp _repl_continue
246
247     _repl_invalid_addr:
248     push invalidaddr_str
249     call printf
250     jmp _repl_continue
251
252     _repl_continue:
253     jmp _repl_loop
254     
255     _repl_exit:
256
257     %undef CMDSTR
258
259     mov esp, ebp
260     pop ebp
261     ret
262