
;%define STACK_SIZE 100000
%define STACK_SIZE 21000000

section .data
	hello:     db 'Hello world!',10
	helloLen:  equ $-hello

section .bss
        stack:       resd STACK_SIZE  
        eof_reached: resd 1
        val:         resd 1
        _ch:         resd 1
        temp:        resd 1
        save_stack:  resd 2

section .text

	global _START

_syscall: ; only used by OpenBSD
        int  0x80
        ret

_my_exit:
	EXIT_ ; sys_exit

_read_char:
        GETCHAR
        ret

_write_char:
        sub  edi, 4
        PUTCHAR
        ret

write_char_n:
L1:
        test  eax, eax
        je    L2
        dec   eax
        sub   edi, 4
        push  eax
        PUTCHAR
        pop   eax
        jmp   L1
L2:
        ret

write_packed_char_n:
        mov   ebx, eax
        shr   ebx, 2
        mov   ecx, ebx
        shl   ebx, 2
        sub   eax, ebx
        mov   edx, eax ; edx = count - ((count >> 2) << 2
        mov   eax, ecx ; eax = count >> 2

        test  edx, edx
        je    WP_L1
        sub   edi, 4
        mov   ecx, [edi] ; ecx = top of stack
        mov   ebx, ecx
        and   ebx, 255
        mov   [edi], ebx
        push  eax
        push  ecx
        push  edx
        PUTCHAR
        pop   edx
        pop   ecx
        pop   eax
        cmp   edx, 1
        jle   WP_L1
        shr   ecx, 8
        mov   ebx, ecx
        and   ebx, 255
        mov   [edi], ebx
        push  eax
        push  ecx
        push  edx
        PUTCHAR
        pop   edx
        pop   ecx
        pop   eax
        cmp   edx, 2
        jle   WP_L1
        shr   ecx, 8
        mov   ebx, ecx
        and   ebx, 255
        mov   [edi], ebx
        push  eax
        push  ecx
        push  edx
        PUTCHAR
        pop   edx
        pop   ecx
        pop   eax

WP_L1:
        test  eax, eax
        je    WP_L2
        dec   eax
        sub   edi, 4
        mov   ecx, [edi]
        mov   ebx, ecx
        and   ebx, 255
        mov   [edi], ebx
        push  eax
        push  ecx
        PUTCHAR
        pop   ecx
        pop   eax
        shr   ecx, 8
        mov   ebx, ecx
        and   ebx, 255
        mov   [edi], ebx
        push  eax
        push  ecx
        PUTCHAR
        pop   ecx
        pop   eax
        shr   ecx, 8
        mov   ebx, ecx
        and   ebx, 255
        mov   [edi], ebx
        push  eax
        push  ecx
        PUTCHAR
        pop   ecx
        pop   eax
        shr   ecx, 8
        mov   ebx, ecx
        and   ebx, 255
        mov   [edi], ebx
        push  eax
        push  ecx
        PUTCHAR
        pop   ecx
        pop   eax
        jmp   WP_L1
WP_L2:
        ret

_write_int:
        test eax, eax
        jge  L7
        mov  ebx, temp
        mov  [ebx], eax

        ; write '-'
        mov  edx, 45
        mov  [edi], edx
        PUTCHAR

        mov  ebx, temp
        mov  eax, [ebx]
        neg  eax

L7:
        mov  ebx, temp ; used for counting digits
        xor  ecx, ecx
        mov  [ebx], ecx

L6:
        xor  edx, edx
        mov  ecx, 10
        div  ecx ; eax = edx:eax / 10
        add  edx, 48 ; edx = edx:eax mod 10 + '0'

        ; push edx on the stack

        mov  [edi], edx
        add  edi, 4

        mov  ebx, temp ; increment digit count
        mov  ecx, [ebx]
        inc  ecx
        mov  [ebx], ecx
        test eax, eax
        jne  L6

        ; display digits

        mov  ebx, temp ; get digit count
        mov  eax, [ebx]

        call write_char_n

        ret

my_mul:
        sub  edi, 4
        mov  eax, [edi]
        mov  ecx, edi
        sub  ecx, 4
        mov  ebx, [ecx]
        imul ebx
        mov  [ecx], eax
        ret

my_div:
        sub  edi, 4
        mov  eax, [edi]
        cdq ; sign extends edx if eax is negative
        mov  ecx, edi
        sub  ecx, 4
        mov  ebx, [ecx]
        idiv ebx
        mov  [ecx], eax
        ret

my_mod:
        sub  edi, 4
        mov  eax, [edi]
        cdq ; sign extends edx if eax is negative
        mov  ecx, edi
        sub  ecx, 4
        mov  ebx, [ecx]
        idiv ebx
        mov  [ecx], edx
        ret

my_abs:
        mov  ecx, edi
        sub  ecx, 4
        mov  eax, [ecx]
        test eax, eax
        jg   L11
        neg  eax
        mov  [ecx], eax
L11:
        ret

; useful routine to debug stack leaks

check_stack_overflow:
        mov    ebx, edi
        mov    eax, stack
        sub    ebx, eax
        shr    ebx, 2
        mov    ecx, STACK_SIZE
        cmp    ebx, ecx
        jl     no_overflow
	EXIT_ ; sys_exit
no_overflow:
        ret

_START:
        xor  eax, eax
        mov  ebx, eof_reached
        mov  [ebx], eax
        mov  eax, 32
        mov  ebx, _ch
        mov  [ebx], eax

        ; initialize stack

;       mov  eax, stack
;       mov  ebx, eax
;       mov  ecx, 4 * STACK_SIZE
;       add  ebx, ecx
;       xor  edx, edx
;stack_init_loop:
;       mov  [eax], edx
;       add  eax, 4
;       cmp  eax, ebx
;       jl   stack_init_loop
