Mail Archives: djgpp/2001/01/31/11:36:37
That's right. I do the following thing (skip irrelevant code and see prinf()
implementation):
---------8<----------
////////////////////////
// CONIO.H/LIB MODULE //
////////////////////////
#include "conio.h"
//#include "string.h"
#include "ints.h"
#include "ports.h"
/* INNER DATA */
byte *_screen_base = (byte *) 0xB8000;
dword _cursor_x = 0, _cursor_y = 0;
dword _scrolling = 1;
byte _textattr = 7;
volatile byte _keybuf[_KEYBUF_SIZE];
volatile dword _kbhead = 0, _kbtail = 0, _kbcnt = 0;
byte _symmap[256] =
{"\0\0331234567890-=\b\tQWERTYUIOP[]\r\0ASDFGHJKL;\'`\0\\ZXCVBNM,./\0*\0
"};
// \0 - zero
// \033 - esc (octal 33 = decimal 27 )
// \b - backspace
// \t - tab
// \r - return - enter
// \\ - "\"
/* FUNCTIONS */
// Updates location of a hardware text cursor
void _update_cursor() {
dword offs = _cursor_y*80+_cursor_x;
outportb (0x3D4, 0x0F); outportb (0x3D5, offs & 0xFF);
offs>>=8;
outportb (0x3D4, 0x0E); outportb (0x3D5, offs & 0xFF);
}
// Must be run first
void conio_init() {
byte *eq = (byte *) 0x410;
// let's find out wether screen is color or mono and find
// appropriate value for the screen pointer
if (((*eq) & 0x30) == 0x30) _screen_base = (byte *) 0xB0000;
else _screen_base = (byte *) 0xB8000;
_textattr = 7;
_cursor_x = _cursor_y = 0;
_update_cursor();
}
// Locates the cursor
void gotoxy (dword x, dword y) {
_cursor_x = x;
_cursor_y = y;
_update_cursor();
}
// Reads cursor X
dword wherex() {
return _cursor_x;
}
// Reads cursor Y
dword wherey() {
return _cursor_y;
}
// Sets foreground color
void textbackground (byte color) {
_textattr = (_textattr & 0x0F) | (color << 4);
}
// Sets ink color
void textcolor (byte color) {
_textattr = (_textattr & 0xF0) | (color & 0x0F);
}
// Clears the screen with current color (_textattr)
void clrscr() {
__asm__ __volatile__ ("
movl %1, %%edi
movl $80*25, %%ecx
movb %0, %%ah
movb $0, %%al
cld
rep
stosw"
:
: "g" (_textattr), "g" (_screen_base)
: "eax", "ecx", "edi"
);
gotoxy (0, 0);
}
// Inner routine - do not use!
void __scroll() {
byte *s;
int i;
memcpy (_screen_base, _screen_base+80*2, 80*24*2);
s = _screen_base + 80*24*2;
for (i=0;i<80;i++) {
*s++ = 0;
*s++ = _textattr;
}
}
// Inner routine - do not use!
void __putch (char c) {
dword offs = (_cursor_x + _cursor_y*80)*2;
_screen_base[offs] = c;
_screen_base[offs+1] = _textattr;
}
// Puts a character to the screen (adjusts cursor position)
// Few control characters available:
// \t, \n, \r, \b
void putch (char c) {
switch (c) {
case '\t' :
do {
__putch (' ');
if (++_cursor_x>=80) {
_cursor_x = 0;
if (++_cursor_y>=25) {
if (_scrolling) {
_cursor_y=24;
__scroll();
} else
_cursor_y = 0;
};
};
} while (_cursor_x % 8);
break;
case '\n' :
if (++_cursor_y>=25) {
if (_scrolling) {
_cursor_y=24;
__scroll();
} else
_cursor_y = 0;
};
break;
case '\r' :
_cursor_x = 0;
break;
case '\b' :
if (_cursor_x > 0) _cursor_x--;
break;
default:
__putch (c); _cursor_x++;
break;
};
if (_cursor_x>=80) {
_cursor_x = 0;
if (++_cursor_y>=25) {
if (_scrolling) {
_cursor_y=24;
__scroll();
} else
_cursor_y = 0;
};
};
_update_cursor();
}
/*
printf() stuff
*/
/* Inner routine - do not use! */
void __puts (char *s, int len, int zero) {
int l=0;
char *p;
p=s;
while (*p++) l++; /* strlen(s) */
while (len > l) { /* left-padded */
if (zero) putch ('0');
else putch (0x20);
len--;
};
while (*s)
putch (*s++);
while (-len > l) { /* right-padded */
putch (0x20);
len++;
}
}
/* Inner routine - do not use! */
void __putd (int d, int len, int zero) {
char s[12], *p;
int neg=0;
s[11] = 0;
s[10] = '0';
p = &s[10];
if (d<0) {
neg = 1;
d =- d;
};
if (d) {
while (d) {
*p-- = d%10+'0';
d /= 10;
};
p++;
};
if (neg) {
p--;
*p = '-';
};
__puts (p, len, zero);
}
/* Inner routine - do not use! */
void __putud (unsigned int d, int len, int zero) {
char s[12], *p;
s[11] = 0;
s[10] = '0';
p = &s[10];
if (d) {
while (d) {
*p-- = d%10+'0';
d /= 10;
};
p++;
};
__puts (p, len, zero);
}
/* Inner routine - do not use! */
void __puth (unsigned int h, int upper, int len, int zero) {
char s[12], *p, c;
s[11] = 0;
s[10] = '0';
p = &s[10];
if (h) {
while (h) {
if (upper) { if ((c = h%16 + '0') > '9') c+='A'-'9'-1; }
else { if ((c = h%16 + '0') > '9') c+='a'-'9'-1; };
*p-- = c;
h /= 16;
};
p++;
};
__puts (p, len, zero);
}
/* Inner routine - do not use! */
void __putld (long d, int len, int zero) {
char s[12], *p;
int neg=0;
s[11] = 0;
s[10] = '0';
p = &s[10];
if (d<0) {
neg = 1;
d =- d;
};
if (d) {
while (d) {
*p-- = d%10+'0';
d /= 10;
};
p++;
};
if (neg) {
p--;
*p = '-';
};
__puts (p, len, zero);
}
/* Inner routine - do not use! */
void __putlud (unsigned long d, int len, int zero) {
char s[12], *p;
s[11] = 0;
s[10] = '0';
p = &s[10];
if (d) {
while (d) {
*p-- = d%10+'0';
d /= 10;
};
p++;
};
__puts (p, len, zero);
}
/* Inner routine - do not use! */
void __putlh (unsigned long h, int upper, int len, int zero) {
char s[12], *p, c;
s[11] = 0;
s[10] = '0';
p = &s[10];
if (h) {
while (h) {
if (upper) { if ((c = h%16 + '0') > '9') c+='A'-'9'-1; }
else { if ((c = h%16 + '0') > '9') c+='a'-'9'-1; };
*p-- = c;
h /= 16;
};
p++;
};
__puts (p, len, zero);
}
/* Puts a formated ASCIIZ string to the screen (adjusts cursor position) */
/* Currently supports these specifiers: */
/* %% for "%", */
/* %c for char */
/* %s for ASCIIZ strings */
/* %d and %i for int */
/* %u for unsigned int */
/* %x and %X for unsigned int */
/* and these input-size modifiers: */
/* l for long int */
/* Supported width specifiers: */
/* n for left-padded output (n>0) */
/* -n for right-padded output (n>0) */
/* 0n for 0 left-padded output (n>0) */
void printf (const char *fmt, ...) {
va_list arglist;
int x=0;
int is_long;
int len;
int neg;
int zero_pad;
char *str;
int dec;
unsigned int udec;
unsigned int hex;
long ldec;
unsigned long ludec;
unsigned long lhex;
va_start (arglist, fmt);
while (fmt[x]) {
if (fmt[x] == '%') {
is_long = len = zero_pad = 0;
neg = 1;
x++;
if (fmt[x] == '-') {
neg = -1;
x++;
};
if (fmt[x] == '0') {
zero_pad = 1;
x++;
};
while ((fmt[x] >= '0') && (fmt[x] <= '9')) {
len = len * 10 + (unsigned int)(fmt[x]-'0');
x++;
};
len *= neg;
if (fmt[x] == 'l') {
is_long = 1;
x++;
};
switch (fmt[x]) {
case '%':
putch ('%');
break;
case 's':
str = va_arg (arglist, char*);
__puts (str, len, 0);
break;
case 'c':
dec = (int)va_arg (arglist, char);
putch (dec);
break;
case 'd':
case 'i':
if (is_long) {
ldec = va_arg (arglist, long);
__putld (ldec, len, zero_pad);
} else {
dec = va_arg (arglist, int);
__putd (dec, len, zero_pad);
};
break;
case 'u':
if (is_long) {
ludec = va_arg (arglist, unsigned long);
__putlud (ludec, len, zero_pad);
} else {
udec = va_arg (arglist, unsigned int);
__putud (udec, len, zero_pad);
};
break;
case 'x':
if (is_long) {
lhex = va_arg (arglist, unsigned long);
__putlh (lhex, 0, len, zero_pad);
} else {
hex = va_arg (arglist, unsigned int);
__puth (hex, 0, len, zero_pad);
};
break;
case 'X':
if (is_long) {
lhex = va_arg (arglist, unsigned long);
__putlh (lhex, 1, len, zero_pad);
} else {
hex = va_arg (arglist, unsigned int);
__puth (hex, 1, len, zero_pad);
};
break;
default:
putch (fmt[x]);
break;
};
} else {
if (fmt[x] == '\n') {
putch ('\r');
putch ('\n');
} else
putch (fmt[x]);
};
x++;
};
va_end (arglist);
}
// Returns non-zero result in case of pressed key
int kbhit() {
return _kbcnt;
}
// Returns scan code of the pressed key
char getscan() {
char r;
while (!_kbcnt) {};
r = _keybuf[_kbhead++];
if (_kbhead == _KEYBUF_SIZE) _kbhead = 0;
_kbcnt--;
return r;
}
// Returns ASCII code (in upper case) of the pressed key
char getch() {
return _symmap[(int)getscan()];
}
// Cleans the keyboard buffer
void clear_keybuf() {
disable();
_kbhead = _kbtail = _kbcnt=0;
enable();
}
---------8<----------
--
Alexei A. Frounze
alexfru [AT] chat [DOT] ru
frounze [AT] ece [DOT] rochester [DOT] edu
http://alexfru.chat.ru
http://members.xoom.com/alexfru/
http://welcome.to/pmode/
"Hans-Bernhard Broeker" <broeker AT physik DOT rwth-aachen DOT de> wrote in message
news:9598k2$nn0$1 AT nets3 DOT rz DOT RWTH-Aachen DOT DE...
> Christian Merz <cmerz AT bndlg DOT de> wrote:
> > can anybody tell me how the va_list, va_start() and va_end() works?
>
> Unless you want to re-implement them on your own, in assembly or so,
> you don't need to know how they work. Just how you're supposed to use
> them.
>
> > I have to include the "<stdarg.h>" file, because I'll write my own
> > printf function for my os, but I guess va_list, va_start() and
> > va_end() uses some memory allocation routines for allocating some
> > lists and so on , right?
>
> No memory allocation, no. The arguments have been put on the stack by
> the calling function. All va_start() and friends to is hand them over
> to your code, one by one.
>
> > So what I have to do to get the "va" stuff working?
>
> Just use them. They already do work --- if they don't, you're not done
> yet with porting GCC to that OS :-)
>
> info libc alpha varargs
>
> has all you need to know, I think.
> --
> Hans-Bernhard Broeker (broeker AT physik DOT rwth-aachen DOT de)
> Even if all the snow were burnt, ashes would remain.
- Raw text -