3 ; Code for Linux on IA-32.
7 section .text ; start of code
8 global _lmStart ; export the entry point function
13 mov [__start_esp], esp
16 mov esp, [__start_esp]
17 ; Cleanup can be done here if necessary
26 ; lmExit - Terminate safely from any position in the program
29 lmExit: ; void lmExit(int exitstatus)
30 mov eax, [esp+4] ; pass the exit status through as eax
31 jmp _start_end ; poor man's exception handling
32 ; ret is not necessary
38 ; lmPrintChar - Print one character to stdout (8-bit in 32-bit, LSB)
41 lmPrintChar: ; void lmPrintChar(int chr)
42 push eax ; will be: syscall number
43 push ebx ; will be: stdout fd
44 push ecx ; will be: character start address
45 push edx ; will be: character counter
47 mov edx, 1 ; print one char
48 lea ecx, [esp+20] ; address of the char
49 mov ebx, 1 ; stdout fd
63 ; lmPrintString - Print a null-terminated string to stdout
66 lmPrintString: ; void lmPrintString(char *string)
67 push eax ; will be: syscall number
68 push ebx ; will be: stdout fd
69 push ecx ; will be: character start address
70 push edx ; will be: character counter
72 mov eax, 0 ; prepare for holding a char
73 mov ecx, [esp+20] ; string start address
74 mov edx, -1 ; init char counter to 0
77 inc edx ; char_counter++
78 mov al, [ecx+edx] ; check next char
79 cmp al, 0 ; if != '\0' continue
80 jne _print_string_loop
82 mov ebx, 1 ; stdout fd
96 ; lmPrintInt32s - Print an integer to stdout (signed, 32-bit)
99 lmPrintInt32s: ; void lmPrintInt(int num)
100 push eax ; will be: dividend
101 push ebx ; will be: divisor
102 push ecx ; will be: character start address
103 push edx ; will be: character counter
104 mov eax, [esp+20] ; load num
105 sub esp, 12 ; make space for converted integer
106 lea ecx, [esp+11] ; string offset counter, start at lastchar+1
107 ; so writing ends at 10 and char 11 is reserved
109 mov ebx, 10 ; always divide by 10
111 cmp eax, dword 0 ; if the number is negative, negate
113 neg eax ; great fun at -2147483648. Overflow ftw!
119 dec ecx ; write next char
124 cmp [esp+32], dword 0 ; check for negative number
125 jge _print_int_end ; skip for positive
127 mov [ecx], byte '-' ; add - sign
131 sub edx, ecx ; number of chars
132 mov ebx, 1 ; stdout fd
134 int 0x80 ; let the number speak
147 ; lmReadChar - Read a character from stdin (8-bit in 32-bit, LSB)
150 lmReadChar: ; int lmReadChar(void)
155 sub esp, 4 ; make room for character to be read
157 mov edx, 1 ; number of chars
158 mov ecx, esp ; character buffer
159 mov ebx, 0 ; stdin fd
164 jne _read_char_ok ; No end of input -> return char
166 mov eax, 0 ; End of Input -> return 0
184 ; lmReadInt32s - Read an integer from stdin (signed, 32-bit)
185 ; Terminated by EOF or LF
188 lmReadInt32s: ; int lmReadInt(void)
192 push esi ; negative number info
193 push edi ; actual number
195 sub esp, 4 ; make room for character to be read
197 mov esi, 0 ; 0 = positive
198 mov edi, 0 ; start with 0
202 mov edx, 1 ; number of chars
203 mov ecx, esp ; character buffer
204 mov ebx, 0 ; stdin fd
209 je _read_int_neg ; End of input
215 jne _read_int_process_digit
219 _read_int_process_digit:
221 jb _read_int_neg ; char < '0'
223 ja _read_int_neg ; char > '9'
226 imul edi, 10 ; shift old digits
227 add edi, eax ; add new digit
234 jz _read_int_skip_loop
238 _read_int_skip_loop: ; read and skip until newline is encountered
240 je _read_int_end ; if newline found -> end reading
242 mov edx, 1 ; number of chars
243 mov ecx, esp ; character buffer
244 mov ebx, 0 ; stdin fd
249 je _read_int_end ; End of input -> end reading
251 jmp _read_int_skip_loop
255 mov eax, edi ; Return value: The number read