section .data hello db ' ) Hello, world!',10 ; Our dear string helloLen equ $ - hello ; Length of our dear string section .bss loopctr resd 1 looplimit resd 1 stringbuf resb 16 ; XXX - String for ASCII version of number (lib_print_number) stringlen resb 1 ; XXX - Length of string (lib_print_number) section .text global _start _start: mov dword [loopctr],0 mov dword [looplimit],1000 pop ebx ; argc (argument count) pop ebx ; argv[0] (argument 0, the program name) pop ebx ; The first real arg, a filename mov eax,8 ; The syscall number for creat() (we already have the filename in ebx) mov ecx,00644Q ; Read/write permissions in octal (rw_rw_rw_) int 80h ; Call the kernel ; Now we have a file descriptor in eax test eax,eax ; Lets make sure the file descriptor is valid js skipWrite ; If the file descriptor has the sign flag ; (which means it's less than 0) there was an oops, ; so skip the writing. Otherwise call the filewrite "procedure" call fileWrite skipWrite: mov ebx,eax ; If there was an error, save the errno in ebx mov eax,1 ; Put the exit syscall number in eax int 80h ; Bail out ; proc fileWrite - write a string to a file fileWrite: mov ebx,eax ; sys_creat returned file descriptor into eax, now move into ebx mov eax,4 ; sys_write ; ebx is already set up mov ecx,hello ; We are putting the ADDRESS of hello in ecx mov edx,helloLen ; This is the VALUE of helloLen because it's a constant (defined with equ) jmp myloop myloop: call lib_print_number ; XXX - First write the contents of loopctr to the file push eax int 80h ; this is where my string is written so the print number needs to be called first pop eax inc dword [loopctr] push edx mov edx,[loopctr] cmp dword edx,[looplimit] pop edx je end jmp myloop ; endp fileWrite end: mov eax,6 ; sys_close (ebx already contains file descriptor) int 80h ret lib_print_number: ; XXX from here to end of file -- all new pusha push ebx ; Save the file descriptor for now mov eax, 0 ; Start converting number to ASCII mov word ax, [loopctr] mov edi, stringbuf mov ebx, 10 ; Base of the decimal system mov ecx, 0 ; Number of digits generated .next_divide: mov edx, 0 ; EAX extended to (EDX,EAX) div ebx ; Divide by the number-base push edx ; Save remainder on the stack inc ecx ; And count this remainder cmp eax, 0 ; Was the quotient zero? jne .next_divide ; No, do another division mov byte [stringlen], cl ; Save length of string .next_digit: pop eax ; Else pop recent remainder add al, '0' ; And convert to a numeral stosb ; Store to memory-buffer loop .next_digit ; Again for other remainders mov al, 10 ; Store carriage return char stosb ; Now write the string to the screen mov eax, 4 ; sys_write kernel call pop ebx ; Get file descriptor back mov ecx, stringbuf mov edx, 0 mov byte dl, [stringlen] int 0x80 ; Call kernel popa ret