/*
 *  minimal printf
 */
#define	MSGLEN	512

.global	printf
printf:
	pushal				// push 8x4 bytes = 32 bytes
	leal	36(%esp),%edx		// pointer to format
	movl	(%edx),%esi		// src = format
	enter	$MSGLEN,$0		// buffer[MSGLEN]
	movl	%esp,%edi		// dest = buffer
	cld

.Lnextfmt:
.Lcopyloop:
	lodsb				// al = *(src++)
	or	%al,%al			// al == 0 ?
	jnz	.Lnowrite

	movl	%edi,%edx		// dest
	subl	%esp,%edx		// dest - &buffer[] = length
	movl	%esp,%ecx		// &buffer[]
	xorl	%ebx,%ebx
	incl	%ebx			// 1 --> stdout
	push	$4			// 4 --> __NR_write
	popl	%eax
	int	$0x80			// write(1,buffer,length)
	leave				// undo buffer, local vars (ebp --> esp)
	popal
	ret

.Lnowrite:
	stosb
	cmpb	$'%',%al
	jnz	.Lnextfmt
	decl	%edi

.Lformat:
	addl	$4,%edx
	movl	(%edx),%ebx

	lodsb
	cmpb	$'s',%al
	jz	stringfmt

/*
 *  format %i
 */
intfmt:
	pushl	%ebp
	pushl	%edx
	xorl	%ebp,%ebp
	movl	$0x3b9aca00,%ecx
	movb	$'-',%al
	neg	%ebx
	jnle	.Lsign
	neg	%ebx
.Lmain:
	xchgl	%eax,%ebx		// short for `movl %ebx,%eax'
	cdq				// %edx:%eax <-- sign extend %eax
	divl	%ecx,%eax		// %eax = N, %edx = rest
	movl	%edx,%ebx		// save rest
	decl	%ecx
	jecxz	.Lnum
/*
	leal	1(%ecx,%eax),%ecx
*/
	incl	%ecx
	addl	%ecx,%eax
	cdq
	push	$10
	popl	%ecx
	divl	%ecx,%eax		// %eax = new %ecx, %edx = N
	xchgl	%eax,%ecx
	xchgl	%eax,%edx
	addl	%ebp,%eax
	jz	.Lskip
.Lnum:
	or	$0x30,%ebp
	or	%ebp,%eax
.Lsign:
	stosb
.Lskip:
	incl	%ecx
	loop	.Lmain
	popl	%edx
	popl	%ebp
	jmp	.Lnextfmt

/*
 *  format %s
 */
stringfmt:
.Lstrcpy:
	movb	(%ebx),%al
	or	%al,%al
	jz	.Lnextfmt
	incl	%ebx
	stosb
	jmp	.Lstrcpy
