⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 printf_fast.c

📁 很少见的源码公开的msc51和z80的c编译器。
💻 C
字号:
/* Fast printf routine for use with sdcc/mcs51 * Copyright (c) 2001, Paul Stoffregen, paul@pjrc.com * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This library 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. */// include support for 32 bit base 10 integers (%ld and %lu)#define LONG_INT// include support for minimum field widths (%8d, %20s)#define FIELD_WIDTH/* extern void putchar(char ); */static bit long_flag, short_flag, print_zero_flag, negative_flag;#ifdef FIELD_WIDTHstatic bit field_width_flag;static data unsigned char field_width;#endifvoid printf_fast(code char *fmt, ...) reentrant{	fmt;	/* supress unreferenced variable warning */	_asmprintf_begin:	mov	a, _bp		// r0 will point to va_args (stack)	add	a, #253	mov	r0, a		// r0 points to MSB of fmt	mov	dph, @r0	dec	r0	mov	dpl, @r0	// dptr has address of fmt	dec	r0printf_main_loop:	clr	a	movc	a, @a+dptr	// get next byte of fmt string	inc	dptr	//cjne	a, #'%', printf_normal	cjne	a, #37, printf_normalprintf_format:	clr	_long_flag	clr	_short_flag	clr	_print_zero_flag	clr	_negative_flag#ifdef FIELD_WIDTH	clr	_field_width_flag	mov	_field_width, #0#endifprintf_format_loop:	clr	a	movc	a, @a+dptr	// get next byte of data format	inc	dptr	/* parse and consume the field width digits, even if */	/* we don't build the code to make use of them */	add	a, #198	jc	printf_nondigit1	add	a, #10	jnc	printf_nondigit2#ifdef FIELD_WIDTHprintf_digit:	setb	_field_width_flag	mov	r1, a	mov	a, _field_width	mov	b, #10	mul	ab	add	a, r1	mov	_field_width, a#endif	sjmp	printf_format_loopprintf_nondigit1:	add	a, #10printf_nondigit2:	add	a, #48printf_format_l:	//cjne	a, #'l', printf_format_h	cjne	a, #108, printf_format_h	setb	_long_flag	sjmp	printf_format_loopprintf_format_h:	//cjne	a, #'h', printf_format_s	cjne	a, #104, printf_format_s	setb	_short_flag	sjmp	printf_format_loopprintf_format_s:	//cjne	a, #'s', printf_format_d	cjne	a, #115, printf_format_d	ljmp	printf_stringprintf_format_d:	//cjne	a, #'d', printf_format_u	cjne	a, #100, printf_format_u	lcall	printf_get_int	ljmp	printf_intprintf_format_u:	//cjne	a, #'u', printf_format_c	cjne	a, #117, printf_format_c	lcall	printf_get_int	ljmp	printf_uintprintf_format_c:	//cjne	a, #'c', printf_format_x	cjne	a, #99, printf_format_x	mov	a, @r0		// Acc has the character to print	dec	r0	sjmp	printf_charprintf_format_x:	//cjne	a, #'x', printf_normal	cjne	a, #120, printf_normal	ljmp	printf_hexprintf_normal:	jz	printf_eotprintf_char:	lcall	printf_putchar	sjmp	printf_main_loopprintf_eot:	ljmp	printf_end	/* print a string... just grab each byte with __gptrget */	/* the user much pass a 24 bit generic pointer */printf_string:	push	dph		// save addr in fmt onto stack	push	dpl	mov	b, @r0		// b has type of address (generic *)	dec	r0	mov	dph, @r0	dec	r0	mov	dpl, @r0	// dptr has address of user's string	dec	r0#ifdef FIELD_WIDTH	jnb	_field_width_flag, printf_str_loop	push	dpl	push	dphprintf_str_fw_loop:	lcall	__gptrget	jz	printf_str_space	inc	dptr	dec	_field_width	mov	a, _field_width	jnz	printf_str_fw_loopprintf_str_space:	lcall	printf_space	pop	dph	pop	dpl#endif // FIELD_WIDTHprintf_str_loop:	lcall	__gptrget	jz	printf_str_done	inc	dptr	lcall	printf_putchar	sjmp	printf_str_loopprintf_str_done:	pop	dpl		// restore addr withing fmt	pop	dph	ljmp	printf_main_loop	/* printing in hex is easy because sdcc pushes the LSB first */printf_hex:	lcall	printf_hex8	jb	_short_flag, printf_hex_end	lcall	printf_hex8	jnb	_long_flag, printf_hex_end	lcall	printf_hex8	lcall	printf_hex8printf_hex_end:	lcall	printf_zero	ljmp	printf_main_loopprintf_hex8:	mov	a, @r0	lcall	printf_phex_msn	mov	a, @r0	dec	r0	ljmp	printf_phex_lsn#ifndef LONG_INTprintf_ld_in_hex:	//mov	a, #'0'	mov	a, #48	lcall	printf_putchar	//mov	a, #'x'	mov	a, #120	lcall	printf_putchar	mov	a, r0	add	a, #4	mov	r0, a	sjmp	printf_hex#endif	/* printing an integer is not so easy.  For a signed int */	/* check if it is negative and print the minus sign and */	/* invert it to a positive integer */printf_int:	mov	a, r5	jnb	acc.7, printf_uint	/* check if negative */	setb	_negative_flag	mov	a, r1			/* invert integer */	cpl	a	addc	a, #1	mov	r1, a	jb	_short_flag, printf_uint	mov	a, r2	cpl	a	addc	a, #0	mov	r2, a	jnb	_long_flag, printf_uint	mov	a, r3	cpl	a	addc	a, #0	mov	r3, a	mov	a, r4	cpl	a	addc	a, #0	mov	r4, a	/* printing integers is a lot of work... because it takes so */	/* long, the first thing to do is make sure we're doing as */	/* little work as possible, then convert the binary int to */	/* packed BCD, and finally print each digit of the BCD number */printf_uint:	jb	_short_flag, printf_uint_ck8	jnb	_long_flag, printf_uint_ck16printf_uint_ck32:	/* it's a 32 bit int... but if the upper 16 bits are zero */	/* we can treat it like a 16 bit integer and convert much faster */#ifdef LONG_INT	mov	a, r3	jnz	printf_uint_begin	mov	a, r4	jnz	printf_uint_begin#else	mov	a, r3	jnz	printf_ld_in_hex	;print long integer as hex	mov	a, r4			;rather than just the low 16 bits	jnz	printf_ld_in_hex#endif	clr	_long_flagprintf_uint_ck16:	/* it's a 16 bit int... but if the upper 8 bits are zero */	/* we can treat it like a 8 bit integer and convert much faster */	mov	a, r2	jnz	printf_uint_begin	setb	_short_flagprintf_uint_ck8:	/* it's an 8 bit int... if it's zero, it's a lot faster to just */	/* print the digit zero and skip all the hard work! */	mov	a, r1	jnz	printf_uint_begin#ifdef FIELD_WIDTH	jnb	_field_width_flag, printf_uint_zero	dec	_field_width	lcall	printf_space#endifprintf_uint_zero:	//mov	a, #'0'	mov	a, #48	lcall	printf_putchar	ljmp	printf_main_loopprintf_uint_begin:	push	dpl	push	dph	lcall	printf_int2bcd		// bcd number in r3/r2/r7/r6/r5#ifdef FIELD_WIDTH	jnb	_field_width_flag, printf_uifw_end#ifdef LONG_INTprintf_uifw_32:	mov	r1, #10	jnb	_long_flag, printf_uifw_16	mov	a, r3	anl	a, #0xF0	jnz	printf_uifw_sub	dec	r1	mov	a, r3	anl	a, #0x0F	jnz	printf_uifw_sub	dec	r1	mov	a, r2	anl	a, #0xF0	jnz	printf_uifw_sub	dec	r1	mov	a, r2	anl	a, #0x0F	jnz	printf_uifw_sub	dec	r1	mov	a, r7	anl	a, #0xF0	jnz	printf_uifw_sub#endifprintf_uifw_16:	mov	r1, #5	jb	_short_flag, printf_uifw_8	mov	a, r7	anl	a, #0x0F	jnz	printf_uifw_sub	dec	r1	mov	a, r6	anl	a, #0xF0	jnz	printf_uifw_subprintf_uifw_8:	mov	r1, #3	mov	a, r6	anl	a, #0x0F	jnz	printf_uifw_sub	dec	r1	mov	a, r5	anl	a, #0xF0	jnz	printf_uifw_sub	dec	r1printf_uifw_sub:	;r1 has the number of digits for the number	mov	a, _field_width	mov	c, _negative_flag	subb	a, r1	jc	printf_uifw_end	mov	_field_width, a#ifdef LONG_INT	push	ar3	push	ar2#endif	push	ar7	push	ar6	push	ar5	lcall	printf_space	pop	ar5	pop	ar6	pop	ar7#ifdef LONG_INT	pop	ar2	pop	ar3#endifprintf_uifw_end:#endifprintf_uint_doit:	jnb	_negative_flag, printf_uint_pos	//mov	a, #"-"	mov	a, #45	lcall	printf_putcharprintf_uint_pos:	jb	_short_flag, printf_uint8#ifdef LONG_INT	jnb	_long_flag, printf_uint16printf_uint32:	push	ar5	push	ar6	push	ar7	mov	dpl, r2	mov	a, r3	mov	dph, a	lcall	printf_phex_msn	mov	a, dph	lcall	printf_phex_lsn	mov	a, dpl	lcall	printf_phex_msn	mov	a, dpl	lcall	printf_phex_lsn	pop	acc	mov	dpl, a	lcall	printf_phex_msn	mov	a, dpl	pop	dph	pop	dpl	sjmp	printf_uint16a#endifprintf_uint16:	mov	dpl, r5	mov	dph, r6	mov	a, r7printf_uint16a:	lcall	printf_phex_lsn	mov	a, dph	lcall	printf_phex_msn	mov	a, dph	sjmp	printf_uint8aprintf_uint8:	mov	dpl, r5	mov	a, r6printf_uint8a:	lcall	printf_phex_lsn	mov	a, dpl	lcall	printf_phex_msn	mov	a, dpl	lcall	printf_phex_lsn	lcall	printf_zero	pop	dph	pop	dpl	ljmp	printf_main_loop	/* read an integer into r1/r2/r3/r4, and msb into r5 */printf_get_int:	mov	a, @r0	mov	r1, a	mov	r5, a	dec	r0	jb	_short_flag, printf_get_done	mov	r2, ar1	mov	a, @r0	mov	r1, a	dec	r0	jnb	_long_flag, printf_get_done	mov	r4, ar2	mov	r3, ar1	mov	a, @r0	mov	r2, a	dec	r0	mov	a, @r0	mov	r1, a	dec	r0printf_get_done:	ret	/* convert binary number in r4/r3/r2/r1 into bcd packed number	 * in r3/r2/r7/r6/r5.  The input number is destroyed in the	 * process, to avoid needing extra memory for the result (and	 * r1 gets used for temporary storage).  dptr is overwritten,	 * but r0 is not changed.	 */printf_int2bcd:	mov	a, r1	anl	a, #0x0F	mov	dptr, #_int2bcd_0	movc	a, @a+dptr	mov	r5, a	mov	a, r1	swap	a	anl	a, #0x0F	mov	r1, a			// recycle r1 for holding nibble	mov	dptr, #_int2bcd_1	movc	a, @a+dptr	add	a, r5	da	a	mov	r5, a	mov	a, r1	orl	a, #16	movc	a, @a+dptr	addc	a, #0	da	a	mov	r6, a	jnb	_short_flag, printf_i2bcd_16	// if 8 bit int, we're done	retprintf_i2bcd_16:	mov	a, r2	anl	a, #0x0F	mov	r1, a	mov	dptr, #_int2bcd_2	movc	a, @a+dptr	add	a, r5	da	a	mov	r5, a	mov	a, r1	orl	a, #16	movc	a, @a+dptr	addc	a, r6	da	a	mov	r6, a	mov	a, r2	swap	a	anl	a, #0x0F	mov	r1, a	mov	dptr, #_int2bcd_3	movc	a, @a+dptr	add	a, r5	da	a	mov	r5, a	mov	a, r1	orl	a, #16	movc	a, @a+dptr	addc	a, r6	da	a	mov	r6, a	mov	a, r1	orl	a, #32	movc	a, @a+dptr	addc	a, #0	da	a	mov	r7, a	jb	_long_flag, printf_i2bcd_32	// if 16 bit int, we're done	retprintf_i2bcd_32:#ifdef LONG_INT	mov	a, r3	anl	a, #0x0F	mov	r1, a	mov	dptr, #_int2bcd_4	movc	a, @a+dptr	add	a, r5	da	a	mov	r5, a	mov	a, r1	orl	a, #16	movc	a, @a+dptr	addc	a, r6	da	a	mov	r6, a	mov	a, r1	orl	a, #32	movc	a, @a+dptr	addc	a, r7	da	a	mov	r7, a	clr	a	addc	a, #0	mov	r2, a	mov	a, r3	swap	a	anl	a, #0x0F	mov	r1, a	mov	dptr, #_int2bcd_5	movc	a, @a+dptr	add	a, r5	da	a	mov	r5, a	mov	a, r1	orl	a, #16	movc	a, @a+dptr	addc	a, r6	da	a	mov	r6, a	mov	a, r1	orl	a, #32	movc	a, @a+dptr	addc	a, r7	da	a	mov	r7, a	mov	a, r1	orl	a, #48	movc	a, @a+dptr	addc	a, r2	da	a	mov	r2, a	mov	a, r4	anl	a, #0x0F	mov	r1, a	mov	dptr, #_int2bcd_6	mov	r3, #0	lcall	printf_bcd_add10	// saves 27 bytes, costs 5 cycles	mov	a, r4	swap	a	anl	a, #0x0F	mov	r1, a	mov	dptr, #_int2bcd_7printf_bcd_add10:	movc	a, @a+dptr	add	a, r5	da	a	mov	r5, a	mov	a, r1	orl	a, #16	movc	a, @a+dptr	addc	a, r6	da	a	mov	r6, a	mov	a, r1	orl	a, #32	movc	a, @a+dptr	addc	a, r7	da	a	mov	r7, a	mov	a, r1	orl	a, #48	movc	a, @a+dptr	addc	a, r2	da	a	mov	r2, a	mov	a, r1	orl	a, #64	movc	a, @a+dptr	addc	a, r3	da	a	mov	r3, a#endif	ret#ifdef FIELD_WIDTHprintf_space_loop:	//mov	a, #' '	mov	a, #32	lcall	printf_putchar	dec	_field_widthprintf_space:	mov	a, _field_width	jnz	printf_space_loop	ret#endif	/* print a hex digit, either upper 4 bit (msn) or lower 4 bits (lsn) */printf_phex_msn:	swap	aprintf_phex_lsn:	anl	a, #15	jnz	printf_phex_ok	jnb	_print_zero_flag, printf_retprintf_phex_ok:	setb	_print_zero_flag	add	a, #0x90	da	a	addc    a, #0x40	da	aprintf_putchar:	push	dph	push	dpl	push	ar0	mov	dpl, a	lcall	_putchar	pop	ar0	pop	dpl	pop	dphprintf_ret:	ret	/* print a zero if all the calls to print the digits ended up */	/* being leading zeros */printf_zero:        jb	_print_zero_flag, printf_ret        //mov	a, #'0'        mov	a, #48        ljmp	printf_putchar  printf_end:	_endasm;}/* * #! /usr/bin/perl * for ($d=0; $d < 8; $d++) { * 	$n = 16 ** $d; * 	for ($p=0; $p < 5; $p++) { * 		last unless (((16 ** $d) * 15) / (10 ** ($p * 2))) % 100; * 		printf "code unsigned char int2bcd_%d_%d[15] = {", $d, $p; * 		for ($i=0; $i < 16; $i++) { * 			printf "0x%02d", * 			   (((16 ** $d) * $i) / (10 ** ($p * 2))) % 100; * 			print ", " if $i < 15; * 		} * 		print "};\n"; * 	} * } */code unsigned char int2bcd_0[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15};code unsigned char int2bcd_1[] = {0x00, 0x16, 0x32, 0x48, 0x64, 0x80, 0x96, 0x12,0x28, 0x44, 0x60, 0x76, 0x92, 0x08, 0x24, 0x40,0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02};code unsigned char int2bcd_2[] = {0x00, 0x56, 0x12, 0x68, 0x24, 0x80, 0x36, 0x92,0x48, 0x04, 0x60, 0x16, 0x72, 0x28, 0x84, 0x40,0x00, 0x02, 0x05, 0x07, 0x10, 0x12, 0x15, 0x17,0x20, 0x23, 0x25, 0x28, 0x30, 0x33, 0x35, 0x38};code unsigned char int2bcd_3[] = {0x00, 0x96, 0x92, 0x88, 0x84, 0x80, 0x76, 0x72,0x68, 0x64, 0x60, 0x56, 0x52, 0x48, 0x44, 0x40,0x00, 0x40, 0x81, 0x22, 0x63, 0x04, 0x45, 0x86,0x27, 0x68, 0x09, 0x50, 0x91, 0x32, 0x73, 0x14,0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02,0x03, 0x03, 0x04, 0x04, 0x04, 0x05, 0x05, 0x06};#ifdef LONG_INTcode unsigned char int2bcd_4[] = {0x00, 0x36, 0x72, 0x08, 0x44, 0x80, 0x16, 0x52,0x88, 0x24, 0x60, 0x96, 0x32, 0x68, 0x04, 0x40,0x00, 0x55, 0x10, 0x66, 0x21, 0x76, 0x32, 0x87,0x42, 0x98, 0x53, 0x08, 0x64, 0x19, 0x75, 0x30,0x00, 0x06, 0x13, 0x19, 0x26, 0x32, 0x39, 0x45,0x52, 0x58, 0x65, 0x72, 0x78, 0x85, 0x91, 0x98};code unsigned char int2bcd_5[] = {0x00, 0x76, 0x52, 0x28, 0x04, 0x80, 0x56, 0x32,0x08, 0x84, 0x60, 0x36, 0x12, 0x88, 0x64, 0x40,0x00, 0x85, 0x71, 0x57, 0x43, 0x28, 0x14, 0x00,0x86, 0x71, 0x57, 0x43, 0x29, 0x14, 0x00, 0x86,0x00, 0x04, 0x09, 0x14, 0x19, 0x24, 0x29, 0x34,0x38, 0x43, 0x48, 0x53, 0x58, 0x63, 0x68, 0x72,0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15};code unsigned char int2bcd_6[] = {0x00, 0x16, 0x32, 0x48, 0x64, 0x80, 0x96, 0x12,0x28, 0x44, 0x60, 0x76, 0x92, 0x08, 0x24, 0x40,0x00, 0x72, 0x44, 0x16, 0x88, 0x60, 0x32, 0x05,0x77, 0x49, 0x21, 0x93, 0x65, 0x38, 0x10, 0x82,0x00, 0x77, 0x55, 0x33, 0x10, 0x88, 0x66, 0x44,0x21, 0x99, 0x77, 0x54, 0x32, 0x10, 0x88, 0x65,0x00, 0x16, 0x33, 0x50, 0x67, 0x83, 0x00, 0x17,0x34, 0x50, 0x67, 0x84, 0x01, 0x18, 0x34, 0x51,0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02};code unsigned char int2bcd_7[] = {0x00, 0x56, 0x12, 0x68, 0x24, 0x80, 0x36, 0x92,0x48, 0x04, 0x60, 0x16, 0x72, 0x28, 0x84, 0x40,0x00, 0x54, 0x09, 0x63, 0x18, 0x72, 0x27, 0x81,0x36, 0x91, 0x45, 0x00, 0x54, 0x09, 0x63, 0x18,0x00, 0x43, 0x87, 0x30, 0x74, 0x17, 0x61, 0x04,0x48, 0x91, 0x35, 0x79, 0x22, 0x66, 0x09, 0x53,0x00, 0x68, 0x36, 0x05, 0x73, 0x42, 0x10, 0x79,0x47, 0x15, 0x84, 0x52, 0x21, 0x89, 0x58, 0x26,0x00, 0x02, 0x05, 0x08, 0x10, 0x13, 0x16, 0x18,0x21, 0x24, 0x26, 0x29, 0x32, 0x34, 0x37, 0x40};#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -