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 ; eax ; will be: syscall number
43 push ebx ; will be: stdout fd
44 ; ecx ; will be: character start address
45 ; edx ; will be: character counter
47 mov edx, 1 ; print one char
48 lea ecx, [esp+8] ; address of the char
49 mov ebx, 1 ; stdout fd
60 ; lmPrintString - Print a null-terminated string to stdout
63 lmPrintString: ; void lmPrintString(char *string)
64 ; eax ; will be: syscall number
65 push ebx ; will be: stdout fd
66 ; ecx ; will be: character start address
67 ; edx ; will be: character counter
69 mov eax, 0 ; prepare for holding a char
70 mov ecx, [esp+8] ; string start address
71 mov edx, -1 ; init char counter to 0
74 inc edx ; char_counter++
75 mov al, [ecx+edx] ; check next char
76 cmp al, 0 ; if != '\0' continue
77 jne _print_string_loop
79 mov ebx, 1 ; stdout fd
90 ; lmPrintInt32s - Print an integer to stdout (signed, 32-bit)
93 lmPrintInt32s: ; void lmPrintInt(int num)
94 ; eax ; will be: dividend
95 push ebx ; will be: divisor
96 ; ecx ; will be: character start address
97 ; edx ; will be: character counter
98 mov eax, [esp+8] ; load num
99 sub esp, 12 ; make space for converted integer
100 lea ecx, [esp+11] ; string offset counter, start at lastchar+1
101 ; so writing ends at 10 and char 11 is reserved
103 mov ebx, 10 ; always divide by 10
105 cmp eax, dword 0 ; if the number is negative, negate
107 neg eax ; great fun at -2147483648. Overflow ftw!
113 dec ecx ; write next char
118 cmp [esp+20], dword 0 ; check for negative number
119 jge _print_int_end ; skip for positive
121 mov [ecx], byte '-' ; add - sign
125 sub edx, ecx ; number of chars
126 mov ebx, 1 ; stdout fd
128 int 0x80 ; let the number speak
138 ; lmReadChar - Read a character from stdin (8-bit in 32-bit, LSB)
141 lmReadChar: ; int lmReadChar(void)
144 sub esp, 4 ; make room for character to be read
146 mov edx, 1 ; number of chars
147 mov ecx, esp ; character buffer
148 mov ebx, 0 ; stdin fd
153 jne _read_char_ok ; No end of input -> return char
155 mov eax, 0 ; End of Input -> return 0
171 ; lmReadInt32s - Read an integer from stdin (signed, 32-bit)
172 ; Terminated by EOF or LF
175 lmReadInt32s: ; int lmReadInt(void)
177 push esi ; negative number info
178 push edi ; actual number
180 sub esp, 4 ; make room for character to be read
182 mov esi, 0 ; 0 = positive
183 mov edi, 0 ; start with 0
187 mov edx, 1 ; number of chars
188 mov ecx, esp ; character buffer
189 mov ebx, 0 ; stdin fd
194 je _read_int_neg ; End of input
200 jne _read_int_process_digit
204 _read_int_process_digit:
206 jb _read_int_neg ; char < '0'
208 ja _read_int_neg ; char > '9'
211 imul edi, 10 ; shift old digits
212 add edi, eax ; add new digit
219 jz _read_int_skip_loop
223 _read_int_skip_loop: ; read and skip until newline is encountered
225 je _read_int_end ; if newline found -> end reading
227 mov edx, 1 ; number of chars
228 mov ecx, esp ; character buffer
229 mov ebx, 0 ; stdin fd
234 je _read_int_end ; End of input -> end reading
236 jmp _read_int_skip_loop
240 mov eax, edi ; Return value: The number read