Autor Thema: kprintf - Problem  (Gelesen 6669 mal)

MrTom3715

  • Beiträge: 38
    • Profil anzeigen
Gespeichert
« am: 13. January 2013, 13:16 »
Hallo,

ich hab vor mein System aufzuräumen bleibe aber bei printf hängen.
Das Steuerzeichen /n funktioniert nicht.  :cry:
Bin mit meinem Latein am Ende.

Hier der Code:
void putc(char c)
{
video[(cursor_y * SCREEN_WIDTH) + cursor_x * 2] = c;
video[(cursor_y * SCREEN_WIDTH) + cursor_x * 2 + 1] = color;
cursor_x++;
printf_res++;
checkcursor();
}

void puts(const char* s)
{
while (*s)
{
putc(*s++);
}
}

void putn(unsigned long t, int s)
{
const char* symbol = "0123456789abcdefghijklmnopqrstuvwxyz";
char buffer[65];
char* r;

if (s > 36)
{
return;
}
r = buffer + 64;
*r = '\0';
do
{
*--r = symbol[t % s];
t /= s;
}
while (t);
puts(r);
}

int printf(const char* fmt, ...)
{
va_list ap;
const char* s;
unsigned long n;
va_start(ap, fmt);
printf_res = 0;

while (*fmt)
{
if (*fmt == '%')
{
fmt++;
switch (*fmt)
{
case 's':
s = va_arg(ap, char*);
puts(s);
break;
case 'p':
case 'x':
n = va_arg(ap, unsigned long int);
putn(n, 10);
break;
case 'd':
case 'u':
n = va_arg(ap, unsigned long int);
putn(n, 10);
break;
case '%':
putc('%');
break;
case '\0':
goto end;
default:
putc('%');
putc(*fmt);
break;
}
}
else if(*fmt == '\n')
{
cursor_y++;
cursor_x = 0;
checkcursor();
}
else if(*fmt == '\t')
{
if(cursor_x > SCREEN_WIDTH - TABULATOR_WIDTH)
{
cursor_x = 0;
cursor_y++;
checkcursor();
}
else
{
cursor_x = cursor_x + TABULATOR_WIDTH;
}
}
else if (*fmt == '\b')
{
cursor_x--;
video[(cursor_y * SCREEN_WIDTH) + cursor_x * 2] = ' ';
}
else if (*fmt == '\r')
{
cursor_x = 0;
}
else if (*fmt == '\v')
{
if(cursor_y > SCREEN_HEIGHT - TABULATOR_HEIGHT)
{
scrolldown(SCREEN_HEIGHT - cursor_y);
}
else
{
cursor_x = 0;
cursor_y = cursor_y + TABULATOR_HEIGHT;
}
}
else if (*fmt == '\f')
{
cls();
}
else if (*fmt == '\\')
{
video[(cursor_y * SCREEN_WIDTH) + cursor_x * 2] = 0x5C;
video[(cursor_y * SCREEN_WIDTH) + cursor_x * 2 + 1] = color;
cursor_x++;
}
else
{
putc(*fmt);
}
fmt++;
}
end:
va_end(ap);
return printf_res;
}

Ich hoffe ihr könnt mir helfen.


MrTom3715

Svenska

  • Beiträge: 1 792
    • Profil anzeigen
Gespeichert
« Antwort #1 am: 13. January 2013, 13:38 »
Ich empfehle dir, die Steuerzeichen im putc zu behandeln, nicht im printf.
« Letzte Änderung: 13. January 2013, 13:39 von Svenska »

MrTom3715

  • Beiträge: 38
    • Profil anzeigen
Gespeichert
« Antwort #2 am: 13. January 2013, 13:52 »
Das habe ich auch schon probiert. Kein Unterschied.

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #3 am: 13. January 2013, 13:55 »
Was heißt denn "funktioniert nicht"? Was passiert?
Dieser Text wird unter jedem Beitrag angezeigt.

MrTom3715

  • Beiträge: 38
    • Profil anzeigen
Gespeichert
« Antwort #4 am: 13. January 2013, 14:00 »
Es passiert gar nichts. Es wird weitergeschrieben als wäre kein \n da.

Svenska

  • Beiträge: 1 792
    • Profil anzeigen
Gespeichert
« Antwort #5 am: 13. January 2013, 15:11 »
Hallo,

Steuerzeichen sind jedenfalls ein Teil der Konsole und gehören damit in putc(). Deine printf()-Implementation wirst du später vermutlich noch für andere Dinge, wie sprintf und Freunde, benutzen wollen - da werden diese Zeichen nicht gesondert behandelt.
Wie und Wo hast du "cursor_x" und "cursor_y" deklariert? Diese Variablen solltest du nur in putc(), scroll() und clear( anfassen (oder wie du die Funktionen genannt hast). Was tut dein checkcursor()? Poste dafür mal den Code. Wofür steht printf_res?

Gruß,
Svenska

MrTom3715

  • Beiträge: 38
    • Profil anzeigen
Gespeichert
« Antwort #6 am: 13. January 2013, 15:39 »
void checkcursor()
{
if(cursor_y == 25)
{
scrolldown(1);
}
if(cursor_x == 79)
{
cursor_x = 0;
cursor_y++;
}
movecursor(cursor_x, cursor_y);
}

void movecursor(uint8_t col, uint8_t row)
{
uint16_t tmp;
tmp = row * SCREEN_WIDTH + col;
outb(0x3D4, 14);
outb(0x3D5, tmp >> 8);
outb(0x3D4, 15);
outb(0x3D5, tmp);
}

cursor_x und cursor_y habe ich global in der Datei console.c deklariert.

Ich werde auch gleich die Steuerzeichen in putc() implementieren.


MrTom3715

MNemo

  • Beiträge: 547
    • Profil anzeigen
Gespeichert
« Antwort #7 am: 13. January 2013, 15:46 »
Es gibt da eine kleine Diskrepanz:
tmp = row * SCREEN_WIDTH + col;
vs.
video[(cursor_y * SCREEN_WIDTH) + cursor_x * 2] = c;
Ersteres geht von SCREEN_WIDTH == 80 letzteres von SCREEN_WIDTH==160 aus.

btw: ein Backslash ist kein Sonderzeichen. ('\\' == 0x5C)
„Wichtig ist nicht, besser zu sein als alle anderen. Wichtig ist, besser zu sein als du gestern warst!“

MrTom3715

  • Beiträge: 38
    • Profil anzeigen
Gespeichert
« Antwort #8 am: 13. January 2013, 16:02 »
@MNemo:
1. Im Wikiartikel steht das auch so. Ich dachte auch man müssten
tmp = row * SCREEN_WIDTH + col *2;nehmen.

2. Ich weiß das ein Backslash kein Sonderzeichen ist. Es ist halt Standard es mit \\ zu schreiben.


MrTom3715

MNemo

  • Beiträge: 547
    • Profil anzeigen
Gespeichert
« Antwort #9 am: 13. January 2013, 16:52 »
@MNemo:
1. Im Wikiartikel steht das auch so. Ich dachte auch man müssten
tmp = row * SCREEN_WIDTH + col *2;nehmen.
Du scheinst mich da falsch verstanden zu haben.
Was willst du den in TMP drin haben?
  Die Nummer des Zeichens an dem der Cursor sein soll; also (Y × maxX + x).
Und was willst du als Index für Video?
  Die Nummer des Bytes an für das Zeichen, da es zwei Byte pro Zeichen sind, also (2 × Y × maxX + 2 × X), bzw. 2×(Y × maxX + X)

Aber egal wie du SCREEN_WIDTH gewählt hast, Anzahl der Zeichen (80) oder Anzahl der Bytes (160), bei einem passt es nicht.


Zitat
2. Ich weiß das ein Backslash kein Sonderzeichen ist. Es ist halt Standard es mit \\ zu schreiben.
Warum machst du dann eine Sonderbehandlung? Dafür gibt es keinen Grund.
„Wichtig ist nicht, besser zu sein als alle anderen. Wichtig ist, besser zu sein als du gestern warst!“

MrTom3715

  • Beiträge: 38
    • Profil anzeigen
Gespeichert
« Antwort #10 am: 13. January 2013, 17:22 »
Ich habe auch keine Erklärung dafür aber es funktioniert bei beiden.
Wenn ich Hallo schreibe erscheint: Hallo_


GCC will bei mir ein einfaches Backslash nicht akzeptieren. GCC vermutet gleich, dass ein Steuerzeichen vorhanden ist.

MNemo

  • Beiträge: 547
    • Profil anzeigen
Gespeichert
« Antwort #11 am: 13. January 2013, 17:31 »
Ich habe auch keine Erklärung dafür aber es funktioniert bei beiden.
Wenn ich Hallo schreibe erscheint: Hallo_
Ja, 0 * 80 = 0 * 160. Der Fehler tritt erst ab der zweiten Zeile(y > 0) auf.

Zitat
GCC will bei mir ein einfaches Backslash nicht akzeptieren. GCC vermutet gleich, dass ein Steuerzeichen vorhanden ist.
Das du das als doppelten \ schreiben musst ist klar. Aber ein '\\' ist ein einfacher Backslash, den du mit putc('\\') ausgeben kannst, ein if (*fmt == '\\') ist also überflüssig.
„Wichtig ist nicht, besser zu sein als alle anderen. Wichtig ist, besser zu sein als du gestern warst!“

MrTom3715

  • Beiträge: 38
    • Profil anzeigen
Gespeichert
« Antwort #12 am: 13. January 2013, 17:35 »
1. Den Fehler werde ich versuchen zu beheben. Spätestens wenn \n funktioniert.

2. Dankeschön!!! Das wusste ich nicht. Du hast mich bereichert. ^^

Edit: SCREEN_WIDTH ist 80 also muss ein Fehler bei der Cursorverschiebung sein.

Hat vielleicht jemand die Lösung für das \n Problem???
« Letzte Änderung: 13. January 2013, 17:36 von MrTom3715 »

MNemo

  • Beiträge: 547
    • Profil anzeigen
Gespeichert
« Antwort #13 am: 13. January 2013, 17:40 »
Edit: SCREEN_WIDTH ist 80 […]

Hat vielleicht jemand die Lösung für das \n Problem???
Ja!
Und was willst du als Index für Video?
  Die Nummer des Bytes für das Zeichen, da es zwei Byte pro Zeichen sind, also (2 × Y × maxX + 2 × X), bzw. 2×(Y × maxX + X)
„Wichtig ist nicht, besser zu sein als alle anderen. Wichtig ist, besser zu sein als du gestern warst!“

MrTom3715

  • Beiträge: 38
    • Profil anzeigen
Gespeichert
« Antwort #14 am: 13. January 2013, 17:44 »
Ich habe es gerade ausprobiert aber es funktioniert nicht.  :cry:

MrTom3715

  • Beiträge: 38
    • Profil anzeigen
Gespeichert
« Antwort #15 am: 13. January 2013, 17:57 »
Hier ist nochmal mein ganzer Code:
#ifndef INCLUDE_include_H
#define INCLUDE_include_H

#include "include.h"

#define SCREEN_WIDTH 80
#define SCREEN_HEIGHT 25
#define TABULATOR_WIDTH 4
#define TABULATOR_HEIGHT 4

static int printf_res;
static char* video = (char*) 0xb8000;
static int cursor_x = 0;
static int cursor_y = 0;
static int color = 0xF0;


inline void outb(uint16_t port, uint8_t data)
{
asm volatile ("outb %0, %1" : : "a" (data), "Nd" (port));
}

void scrolldown(int times)
{
int n;
int p;
for (p = 0; p < times; p++)
{
for (n = 0; n < 160; n++)
video[n] = ' ';
for (n = 0; n < 3839; n++)
video[n] = video[n + 160];
for (n = 3840; n < 4000; n++)
video[n] = ' ';
}
cursor_y = cursor_y - times;
}

void checkcursor()
{
if(cursor_y == 25)
{
scrolldown(1);
}
if(cursor_x == 79)
{
cursor_x = 0;
cursor_y++;
}
movecursor(cursor_x, cursor_y);
}

void putc(char c)
{

if(c == '\n')
{
cursor_y++;
cursor_x = -1;
checkcursor();
}
else if(c == '\t')
{
if(cursor_x > SCREEN_WIDTH - TABULATOR_WIDTH)
{
cursor_x = -1;
cursor_y++;
checkcursor();
}
else
{
cursor_x = cursor_x + TABULATOR_WIDTH;
}
}
else if (c == '\b')
{
video[(cursor_y * SCREEN_WIDTH) + cursor_x * 2] = ' ';
cursor_x--;
}
else if (c == '\r')
{
cursor_x = -1;
}
else if (c == '\v')
{
if(cursor_y > SCREEN_HEIGHT - TABULATOR_HEIGHT)
{
scrolldown(SCREEN_HEIGHT - cursor_y);
}
else
{
cursor_x = -1;
cursor_y = cursor_y + TABULATOR_HEIGHT;
}
}
else if (c == '\f')
{
cls();
}
else
{
cursor_x++;
video[(cursor_y * SCREEN_WIDTH) + cursor_x * 2] = c;
video[(cursor_y * SCREEN_WIDTH) + cursor_x * 2 + 1] = color;
checkcursor();
}
printf_res++;
}

void puts(const char* s)
{
while (*s) {
putc(*s++);
}
}

void putn(unsigned long x, int base)
{
char buf[65];
const char* digits = "0123456789abcdefghijklmnopqrstuvwxyz";
char* p;
 
if (base > 36) {
return;
}
 
p = buf + 64;
*p = '\0';
do {
*--p = digits[x % base];
x /= base;
} while (x);
puts(p);
}

int printf(const char* fmt, ...)
{
va_list ap;
const char* s;
unsigned long n;
 
va_start(ap, fmt);
printf_res = 0;
while (*fmt) {
if (*fmt == '%') {
fmt++;
switch (*fmt) {
case 's':
s = va_arg(ap, char*);
puts(s);
break;
case 'd':
case 'u':
n = va_arg(ap, unsigned long int);
putn(n, 10);
break;
case 'x':
case 'p':
n = va_arg(ap, unsigned long int);
putn(n, 16);
break;
case '%':
putc('%');
break;
case '\0':
goto out;
default:
putc('%');
putc(*fmt);
break;
}
} else {
putc(*fmt);
}
 
fmt++;
  }
 
  out:
va_end(ap);
 
return printf_res;
}

void cls()
{
int u;

cursor_x = 0;
cursor_y = 0;
for(u = 0; u < SCREEN_WIDTH * SCREEN_HEIGHT; u++)
{
cursor_x++;
video[(cursor_y * SCREEN_WIDTH) + cursor_x * 2] = 0;
video[(cursor_y * SCREEN_WIDTH) + cursor_x * 2 + 1] = color;
}
cursor_x = 0;
}

void setcolor(int colorcode)
{
color = colorcode;
}

void movecursor(uint8_t col, uint8_t row)
{
uint16_t tmp;
tmp = (row * SCREEN_WIDTH + col) * 2;
outb(0x3D4, 14);
outb(0x3D5, tmp >> 8);
outb(0x3D4, 15);
outb(0x3D5, tmp);
}

#endif

printf_res zählt die Zeichen. Wenn man wissen möchte wieviele Zeichen der User eingegeben hat, ist das nützlich.

MrTom3715

MrTom3715

  • Beiträge: 38
    • Profil anzeigen
Gespeichert
« Antwort #16 am: 13. January 2013, 18:32 »
Ich habe jetzt printf -> kprintf, putc -> zu kputc usw. gemacht.
Jetzt funktioniert es.

Svenska

  • Beiträge: 1 792
    • Profil anzeigen
Gespeichert
« Antwort #17 am: 14. January 2013, 00:04 »
Hallo,

printf_res zählt die Zeichen. Wenn man wissen möchte wieviele Zeichen der User eingegeben hat, ist das nützlich.
Es ist sogar vorgeschrieben, dass printf die Anzahl der ausgegebenen Zeichen zurückgibt. :-) Ich habe mich nur gewundert, dass du dafür eine globale Variable benutzt. Bei mir gibt putn die Anzahl für die Zahl zurück, d.h. printf zählt selbst.

Globale Variablen sind spätestens dann schlecht, wenn du parallele Ausführung hast, die gleichzeitig was ausgeben möchten (Multitasking!). Dann enthält dein Zähler nämlich Müll (-> Race Condition).

Das #ifndef/#define/#endif gehört übrigens in die "include.h", nicht in die C-Datei. Header-Dateien enthalten selbst keinen Code und C-Dateien werden niemals mit #include eingebunden.

Gruß,
Svenska

MrTom3715

  • Beiträge: 38
    • Profil anzeigen
Gespeichert
« Antwort #18 am: 14. January 2013, 18:51 »
Danke für die Antwort. Habe ich auch nicht gewusst.
Ich include aber auch nur h-Dateien.

Martin Erhardt

  • Beiträge: 165
    • Profil anzeigen
Gespeichert
« Antwort #19 am: 14. January 2013, 20:39 »
Hallo,

printf_res zählt die Zeichen. Wenn man wissen möchte wieviele Zeichen der User eingegeben hat, ist das nützlich.
Es ist sogar vorgeschrieben, dass printf die Anzahl der ausgegebenen Zeichen zurückgibt. :-)
Ja und zwar hier in der STD http://www.acm.uiuc.edu/webmonkeys/book/c_guide/index.html außerdem solltest du die Posix Lib http://pubs.opengroup.org/onlinepubs/9699919799/idx/head.html berücksichtigen. Wenn du diese Libraries GENAU so wie in der Spezifikation mit den selben Funktion Argumenten Headern Makros und Rückgabenwerten im Userland implementierst sollte die Portierung von GCC,git, Python und anderen Programmen ein Kinderspiel sein.(fehlt was außer den Treibern :wink: ?)

Die kernelinternen Funktionen wie "kprintf" kann man zwar so proggen wie man will, aber eine STD POSIX ahnliche Implementierung erhöht die Lesbarkeit für Dritte enorm.

 

Einloggen