summaryrefslogtreecommitdiff
path: root/libmalice.asm
blob: d8c167be886ef5622dbca831ea10b012515f566a (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
; libmalice

; Code for Linux on IA-32.

extern lmMain

section .text ; start of code


global _lmStart ; export the entry point function
_lmStart:	; void lmStart(void)
mov [__start_esp], esp
call lmMain
.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 _lmStart.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)
   ; eax	; will be: syscall number
push ebx 	; will be: stdout fd
   ; ecx 	; will be: character start address
   ; edx	; will be: character counter

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

pop ebx
ret





; lmPrintString - Print a null-terminated string to stdout

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

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

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

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

pop ebx
ret





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

global lmPrintInt32s
lmPrintInt32s:	; void lmPrintInt(int num)
   ; eax	; will be: dividend
push ebx	; will be: divisor
   ; ecx 	; will be: character start address
   ; edx	; will be: character counter
mov eax, [esp+8]	; 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 .loop
neg eax			; great fun at -2147483648. Overflow ftw!

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

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

.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 ebx
ret





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

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

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 .ok		; No end of input -> return char

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

.ok:
mov eax, 0
mov al, [esp]

.end:
add esp, 4
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 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


.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 .neg		; End of input

mov eax, 0
mov al, [esp]

cmp al, '-'
jne .process_digit
mov esi, 1
jmp .next

.process_digit:
cmp al, 0x30
jb .neg		; char < '0'
cmp al, 0x39
ja .neg		; char > '9'

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

jmp .next


.neg:
test esi, esi
jz .skip_loop
neg edi


.skip_loop:	; read and skip until newline is encountered
cmp byte [esp], 0x0a
je .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 .end		; End of input -> end reading

jmp .skip_loop


.end:
mov eax, edi	; Return value: The number read

add esp, 4
pop edi
pop esi
pop ebx
ret







section .data

__start_esp: dd 0