585697bf643d0a2d09f74a024aeda23b8271f264
[sped.git] / sped.asm
1 ; sped - the stupidly pointless editor
2 ; written by pinosaur
3
4 %include "fileutils.S"
5
6 global main
7 extern printf
8 extern fflush
9 extern stdout
10
11 ; macros
12 %macro write_str 2
13     mov eax, 4
14     mov ebx, 1
15     mov ecx, %1
16     mov edx, %2
17     int 0x80
18 %endmacro
19
20 section .data
21     banner_str db `SPED - the stupidly pointless editor\n`, 0x00
22     nofile_str db `no file provided\n`, 0x00
23     readlines_str db `opened file with %i lines\n`, 0x00
24     prompt_str db `sped > `, 0x00
25     invalidcmd_str db `invalid command\n`, 0x00
26     invalidaddr_str db `invalid address\n`, 0x00
27     charcount_str db `read %i chars\n`, 0x00
28     currentline_str db `current line: %i\n`, 0x00
29     echo_str db `%s`, 0x00 ; print strings without format exploit
30
31 section .bss
32     buffer resb 4
33     buffer_lines resb 4
34     cur_line resb 4
35
36 section .text
37 main:
38     %define _ARGC 8
39     %define _ARGV 12
40
41     push ebp
42     mov ebp, esp
43
44     ; read command line args
45     mov ecx, [ebp+_ARGC]
46     cmp ecx, 1
47     jg _main_existing
48     
49     ; display error msg if no file
50     push nofile_str
51     call printf
52     mov eax, 1
53     jmp _main_exit
54
55     _main_existing:
56     mov ebx, DWORD [ebp+_ARGV]
57     add ebx, 4 ; first user arg is filename
58     push DWORD [ebx]
59     call readFile
60
61     mov [buffer], eax
62     mov [buffer_lines], ecx
63     mov DWORD [cur_line], 0x00
64
65     push DWORD [buffer_lines]
66     push readlines_str
67     call printf
68
69     call repl
70
71     mov eax, 0
72     jmp _main_exit
73
74     _main_exit:
75     %undef _ARGC
76     %undef _ARGV
77
78     mov esp, ebp
79     pop ebp
80     ret
81
82 ; prompt for user
83 ; no args - reads from globals
84 repl:
85
86     %define CMDSTR 4 ; the previous line read from user
87
88     push ebp
89     mov ebp, esp
90
91     sub esp, 4
92
93     _repl_loop:
94     
95     ; print the prompt
96     push prompt_str
97     call printf
98     push DWORD [stdout]
99     call fflush
100
101     ; read line from stdin
102     push 0
103     call readLine
104
105     mov DWORD [ebp-CMDSTR], eax
106
107     ; commands are single char for now
108     cmp ecx, 1 
109     jne _repl_invalid_cmd
110
111     ; parse commands
112     mov eax, DWORD [ebp-CMDSTR]
113     mov eax, [eax]
114
115     ; q exists program
116     mov eax, DWORD [ebp-CMDSTR]
117     cmp BYTE [eax], 'q'
118     jne _repl_cmd_quit_end
119     jmp _repl_exit
120     _repl_cmd_quit_end:
121
122     ; p prints current line
123     mov eax, DWORD [ebp-CMDSTR]
124     cmp BYTE [eax], 'p'
125     jne _repl_cmd_print_end
126
127     mov eax, DWORD [cur_line]
128     mov ecx, 4
129     mul ecx
130     add eax, [buffer]
131     push DWORD [eax]
132     push echo_str
133     call printf
134     jmp _repl_continue
135     _repl_cmd_print_end:
136
137     ; n prints the current line number
138     mov eax, DWORD [ebp-CMDSTR]
139     cmp BYTE [eax], 'n'
140     jne _repl_cmd_number_end
141
142     push DWORD [cur_line]
143     push currentline_str
144     call printf
145
146     jmp _repl_continue
147     _repl_cmd_number_end:
148
149     ; - goes to prev line
150     mov eax, DWORD [ebp-CMDSTR]
151     cmp BYTE [eax], '-'
152     jne _repl_cmd_decline_end
153
154     ; make sure we are within bounds
155     mov eax, DWORD [cur_line] 
156     sub eax, 1
157     cmp eax, 0
158     jl _repl_invalid_addr
159     
160     sub DWORD [cur_line], 1
161
162     jmp _repl_continue
163     _repl_cmd_decline_end:
164
165     ; + goes to next line
166     mov eax, DWORD [ebp-CMDSTR]
167     cmp BYTE [eax], '+'
168     jne _repl_cmd_incline_end
169
170     ; make sure we are within bounds 
171     mov eax, DWORD [cur_line] 
172     add eax, 1
173     cmp eax, [buffer_lines]
174     jge _repl_invalid_addr
175     
176     add DWORD [cur_line], 1
177
178     jmp _repl_continue
179     _repl_cmd_incline_end:
180
181
182     jmp _repl_invalid_cmd
183
184     ; some error messages
185     _repl_invalid_cmd:
186     push invalidcmd_str
187     call printf
188     jmp _repl_continue
189
190     _repl_invalid_addr:
191     push invalidaddr_str
192     call printf
193     jmp _repl_continue
194
195     _repl_continue:
196     jmp _repl_loop
197     
198     _repl_exit:
199
200     %undef CMDSTR
201
202     mov esp, ebp
203     pop ebp
204     ret
205