summaryrefslogtreecommitdiff
path: root/libmalice.asm
blob: adb9907d47d9f79ab6fc85fe913fb924a3ff89d6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
; libmalice

; Code for Linux on IA-32.

extern lmMain

section .text ; start of code
global _lmStart ; export the entry point function



_lmStart:
mov [__start_esp], esp
call lmMain
_start_end:
mov esp, [__start_esp]
	; Cleanup can be done here if necessary
mov ebx, eax
mov eax, 1
int 0x80





; lmExit - Terminate safely from any position in the program

global lmExit
lmExit:	; void lmExit(int exitstatus)
mov eax, [esp+4]	; pass the exit status through as eax
jmp _start_end	; poor man's exception handling
	; ret is not necessary





; lmPrintChar - Print one character to stdout (8-bit in 32-bit, LSB)

global lmPrintChar
lmPrintChar:	; void lmPrintChar(int chr)
push eax	; will be: syscall number
push ebx 	; will be: stdout fd
push ecx 	; will be: character start address
push edx	; will be: character counter

mov  edx, 1	; print one char
lea  ecx, [esp+20]	; address of the char
mov  ebx, 1	; stdout fd
mov  eax, 4	; write()
int 0x80

pop edx
pop ecx
pop ebx
pop eax
ret





; lmPrintString - Print a null-terminated string to stdout

global lmPrintString
lmPrintString:	; void lmPrintString(char *string)
push eax	; will be: syscall number
push ebx 	; will be: stdout fd
push ecx 	; will be: character start address
push edx	; will be: character counter

mov  eax, 0		; prepare for holding a char
mov  ecx, [esp+20]	; string start address
mov  edx, -1		; init char counter to 0

_print_string_loop:
	inc  edx		; char_counter++
	mov  al, [ecx+edx]	; check next char
cmp al, 0			; if != '\0' continue
jne _print_string_loop

mov  ebx, 1	; stdout fd
mov  eax, 4	; write()
int 0x80

pop edx
pop ecx
pop ebx
pop eax
ret





; lmPrintInt32s - Print an integer to stdout (signed, 32-bit)

global lmPrintInt32s
lmPrintInt32s:	; void lmPrintInt(int num)
push eax	; will be: dividend
push ebx	; will be: divisor
push ecx 	; will be: character start address
push edx	; will be: character counter
mov eax, [esp+20]	; load num
sub esp, 12		; make space for converted integer
lea ecx, [esp+11]	; string offset counter, start at lastchar+1
			; so writing ends at 10 and char 11 is reserved

mov ebx, 10		; always divide by 10

cmp eax, dword 0	; if the number is negative, negate
jge _print_int_loop
neg eax			; great fun at -2147483648. Overflow ftw!

_print_int_loop:
	mov edx, 0
	idiv ebx
	add edx, 0x30
	dec ecx		; write next char
	mov [ecx], dl
test eax, eax
jne _print_int_loop

cmp [esp+32], dword 0	; check for negative number
jge _print_int_end	; skip for positive
dec ecx
mov [ecx], byte '-'	; add - sign

_print_int_end:
lea edx, [esp+11]
sub edx, ecx	; number of chars
mov  ebx, 1	; stdout fd
mov  eax, 4	; write()
int 0x80	; let the number speak

add esp, 12
pop edx
pop ecx
pop ebx
pop eax
ret





; lmReadChar - Read a character from stdin (8-bit in 32-bit, LSB)

global lmReadChar
lmReadChar:	; int lmReadChar(void)
push ebx
push ecx
push edx

sub esp, 4	; make room for character to be read

mov edx, 1	; number of chars
mov ecx, esp	; character buffer
mov ebx, 0	; stdin fd
mov eax, 3	; read()
int 0x80

cmp eax, 0
jne _read_char_ok	; No end of input -> return char

mov eax, 0		; End of Input -> return 0
jmp _read_char_end

_read_char_ok:
mov eax, 0
mov al, [esp]

_read_char_end:
add esp, 4
pop edx
pop ecx
pop ebx
ret





; lmReadInt32s - Read an integer from stdin (signed, 32-bit)
;                       Terminated by EOF or LF

global lmReadInt32s
lmReadInt32s:	; int lmReadInt(void)
push ebx
push ecx
push edx
push esi	; negative number info
push edi	; actual number

sub esp, 4	; make room for character to be read

mov esi, 0	; 0 = positive
mov edi, 0	; start with 0


_read_int_next:
mov edx, 1	; number of chars
mov ecx, esp	; character buffer
mov ebx, 0	; stdin fd
mov eax, 3	; read()
int 0x80

cmp eax, 0
je _read_int_neg	; End of input

mov eax, 0
mov al, [esp]

cmp al, '-'
jne _read_int_process_digit
mov esi, 1
jmp _read_int_next

_read_int_process_digit:
cmp al, 0x30
jb _read_int_neg	; char < '0'
cmp al, 0x39
ja _read_int_neg	; char > '9'

sub eax, 0x30
imul edi, 10	; shift old digits
add edi, eax	; add new digit

jmp _read_int_next


_read_int_neg:
test esi, esi
jz _read_int_skip_loop
neg edi


_read_int_skip_loop:	; read and skip until newline is encountered
cmp byte [esp], 0x0a
je _read_int_end	; if newline found -> end reading

mov edx, 1	; number of chars
mov ecx, esp	; character buffer
mov ebx, 0	; stdin fd
mov eax, 3	; read()
int 0x80

cmp eax, 0
je _read_int_end	; End of input -> end reading

jmp _read_int_skip_loop


_read_int_end:
mov eax, edi	; Return value: The number read

add esp, 4
pop edi
pop esi
pop edx
pop ecx
pop ebx
ret







section .data

__start_esp: dd 0