/*
 * scnio.S86  -  screen I/O routines for netboot boot images
 *
 * Copyright (C) 2002-2007 Gero Kuhlmann   <gero@gkminix.han.de>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 * $Id: scnio.S86,v 1.5 2007/01/06 18:30:51 gkminix Exp $
 *
 *====================================================================
 */


#include <common.i86>
#include <system/bios.i86>

.file __FILE__
.line __LINE__



/*
 *====================================================================
 *
 * Local definitions
 */
#define BUFSIZE		12		/* size of number buffer */




.line __LINE__
/*
 *====================================================================
 *
 * Start the text segment and define all public entry points
 */

	.text

	.global	prcrlf
	.global	prnstr
	.global	prndwd
	.global	prnwrd
	.global	prnbyt
	.global	prnchr
	.global	prnnum
	.global	cvtnum



/*
 *====================================================================
 *
 * Print a CR/LF onto the console
 * Input:  none
 * Output: none
 * Changed registers: AX
 */
prcrlf:	push	si
	mov	si,offset crlf
	jmp	3f



/*
 *====================================================================
 *
 * Print a number onto the console
 * Input:  EAX  -  Value to print
 *         DL   -  Base
 * Output: none
 * Changed registers: EAX
 */
prnnum:	push	si
	call	cvtnum			# convert number into string
	jmp	3f			# print the string



/*
 *====================================================================
 *
 * Print a string onto the console.
 * Input:  DS:SI -  Pointer to string
 * Output: none
 * Changed registers: AX
 */
prnstr:	push	si
3:	cld
1:	lodsb				# loop over all characters of
	or	al,al			# string
	jz	2f
	call	prnchr			# print character
	jmp	1b
2:	pop	si
	ret



/*
 *====================================================================
 *
 * Print hexadecimal values or characters onto the console
 * Input:  AL, AX or EAX  -  Value or character to print
 * Output: none
 * Changed registers: EAX
 */
prndwd:	push	eax
	shr	eax,16
	call	prnwrd			# print the upper word
	pop	eax
prnwrd:	push	ax
	mov	al,ah
	call	prnbyt			# print the upper byte
	pop	ax
prnbyt: push	ax
	shr	al,4			# prepare upper nibble
	call	prnnib			# print it
	pop	ax
prnnib:	and	al,0x0F			# prepare lower nibble
	add	al,0x30
	cmp	al,0x39			# convert it into hex
	jbe	prnchr
	add	al,0x07
prnchr:	push	bx
	mov	ah,0x0E			# use BIOS to print character
	mov	bx,0x0007
	int	INT_VIDEO
	pop	bx
	ret



/*
 *====================================================================
 *
 * Convert a number into a string
 * Input:  EAX  -  Value to print
 *         DL   -  Base
 * Output: SI   -  Pointer to static string
 * Changed registers: EAX, SI
 */
cvtnum:	push	cx
	push	dx
	mov	si,offset numbuf + BUFSIZE - 1
	mov	byte ptr [si],0		# work from top to bottom
	mov	cx,ax
	shr	eax,16
1:	mov	dh,al
	mov	al,ah
	xor	ah,ah
	div	dl
	xchg	dh,al			# divide the number in AX:CX by
	div	dl			# the number base
	xchg	al,ch
	div	dl
	xchg	al,cl
	div	dl
	and	ah,0x0F
	add	ah,0x30
	cmp	ah,0x39			# the division remainder gets converted
	jbe	2f			# into an ascii character
	add	ah,0x07
2:	cmp	si,offset numbuf	# check for buffer underflow
	jbe	3f
	dec	si
	mov	byte ptr [si],ah	# store character into temporary buffer
	mov	ah,dh
	xchg	al,cl
	xchg	al,ch			# put quotient back into AX:CX
	or	dh,cl
	or	dh,ch			# check if number got completely
	or	dh,al			# converted
	jnz	1b

3:	pop	dx
	pop	cx
	ret




/*
 *====================================================================
 *
 * String and constants definitions
 */
	_rodata

crlf:	.byte	0x0D, 0x0A		# CR/LF string
	.byte	0




/*
 *====================================================================
 *
 * Variable definitions
 */
	.bss

	.lcomm	numbuf,BUFSIZE		# buffer for number value




/*
 *====================================================================
 */
	.end

