Autor Thema: fprintf Funktioniert nicht  (Gelesen 19951 mal)

OsDevNewbie

  • Beiträge: 282
    • Profil anzeigen
    • YourOS Kernel
Gespeichert
« am: 11. March 2013, 21:09 »
Hallo,
ich habe jetzt mal die Funktion printf programmiet, die einfach die Funktion fprintf(stdout, format) aufruft. Ich will eine Zahl formatiert ausgeben lassen. Die Funktion gibt aber immer nur 0 aus. Woran kann denn das liegen? Ich habe es auch schon mit direktem Aufruf von fprintf versucht mit dem selben Ergebnis.
Hier mein Quellcode (Die Funktion fprintf ist noch nicht ganz fertig):
stdio.c
...
int fprintf(FILE *stream, const char *format, ...)
{
va_list arg;
va_start(arg, format);
uint64_t pos = 0;
static char buffer[64];
//char *buffer = malloc(64); //Mehr wird momentan nicht benötigt
if(stream == stdout)
{
for(; *format; format++)
{
switch(*format)
{
case '%': //Formatieren?
switch(*(++format))
{
case 'u': //Unsigned int
utoa(va_arg(arg, uint64_t), buffer);
puts(buffer);
pos += strlen(buffer);
break;
case 'i': //Signed int
case 'b':
itoa(va_arg(arg, int64_t), buffer);
puts(buffer);
pos += strlen(buffer);
break;
case 'f': //Float
ftoa(va_arg(arg, double), buffer);
puts(buffer);
pos += strlen(buffer);
break;
case 'X': //Hex 8
break;
case 'x': //Hex 4
break;
case 'y': //Hex 2
break;
case 's': //String
{
char *temp = va_arg(arg, char*);
puts(temp);
pos += strlen(temp);
}
break;
case 'c': //Char
putchar((char)va_arg(arg, int32_t));
pos++;
break;
case '%': //%
putchar("%");
pos++;
break;
default: //Ansonsten ungültig
format--;
pos--;
break;
}
break;
default: //Ansonsten schreibe das aktuelle Zeichen
putchar(*format);
pos++;
break;
}
}
}
else
pos = EOF;
//free(buffer);
va_end(arg);
return pos;
}

int printf(const char *format, ...)
{
return fprintf(stdout, format);
}
...
Viele Grüsse
OsDevNewbie

Ein Computer ohne Betriebsystem ist nicht mehr wert als ein Haufen Schrott.
Ein Computer ist eine Maschine, die einem Lebewesen das kostbarste klaut, was sie selber nicht hat:
DIE ZEIT DES LEBENS

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #1 am: 11. March 2013, 22:43 »
Die optionalen Parameter vom printf können nicht einfach so an das fprintf weitergereicht werden. Du musst in printf das Zeug mit va_list arg; va_start ... machen, und das dann an eine Funktion (z.B. int vfprintf(FILE *, const char *, va_list arg);) übergeben, die dann die eigentlich Ausgabe macht. Beispiel hier: http://www.cplusplus.com/reference/cstdio/vfprintf/
Dieser Text wird unter jedem Beitrag angezeigt.

OsDevNewbie

  • Beiträge: 282
    • Profil anzeigen
    • YourOS Kernel
Gespeichert
« Antwort #2 am: 11. March 2013, 22:56 »
Also mein Quellcode sieht jetzt so aus:
stdio.c
...
int vfprintf(FILE *stream, const char *format, va_list arg)
{
uint64_t pos = 0;
static char buffer[64];
//char *buffer = malloc(64); //Mehr wird momentan nicht benötigt
if(stream == stdout)
{
for(; *format; format++)
{
switch(*format)
{
case '%': //Formatieren?
switch(*(++format))
{
case 'u': //Unsigned int
utoa(va_arg(arg, uint64_t), buffer);
puts(buffer);
pos += strlen(buffer);
break;
case 'i': //Signed int
case 'b':
itoa(va_arg(arg, int64_t), buffer);
puts(buffer);
pos += strlen(buffer);
break;
case 'f': //Float
ftoa(va_arg(arg, double), buffer);
puts(buffer);
pos += strlen(buffer);
break;
case 'X': //Hex 8
break;
case 'x': //Hex 4
break;
case 'y': //Hex 2
break;
case 's': //String
{
char *temp = va_arg(arg, char*);
puts(temp);
pos += strlen(temp);
}
break;
case 'c': //Char
putchar((char)va_arg(arg, int32_t));
pos++;
break;
case '%': //%
putchar("%");
pos++;
break;
default: //Ansonsten ungültig
format--;
pos--;
break;
}
break;
default: //Ansonsten schreibe das aktuelle Zeichen
putchar(*format);
pos++;
break;
}
}
}
else
pos = EOF;
//free(buffer);
return pos;
}

int fprintf(FILE *stream, const char *format, ...)
{
va_list arg;
va_start(arg, format);
int pos = vfprintf(stream, format, arg);
va_end(arg);
return pos;
}

int printf(const char *format, ...)
{
va_list arg;
va_start(arg, format);
int pos = vfprintf(stdout, format, arg);
va_end(arg);
return pos;
}
...
Er funktioniert aber immer noch nicht korrekt.
Danke für deine Hilfe.
Viele Grüsse
OsDevNewbie

Ein Computer ohne Betriebsystem ist nicht mehr wert als ein Haufen Schrott.
Ein Computer ist eine Maschine, die einem Lebewesen das kostbarste klaut, was sie selber nicht hat:
DIE ZEIT DES LEBENS

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #3 am: 11. March 2013, 23:27 »
Was mir noch auffällt, ist, dass du int64_t bzw. uint64_t bei va_arg nutzt. Das ist bei 32-Bit-Code nicht korrekt.
Dieser Text wird unter jedem Beitrag angezeigt.

Martin Erhardt

  • Beiträge: 165
    • Profil anzeigen
Gespeichert
« Antwort #4 am: 12. March 2013, 00:29 »
Die optionalen Parameter vom printf können nicht einfach so an das fprintf weitergereicht werden. Du musst in printf das Zeug mit va_list arg; va_start ... machen, und das dann an eine Funktion (z.B. int vfprintf(FILE *, const char *, va_list arg);) übergeben, die dann die eigentlich Ausgabe macht. Beispiel hier: http://www.cplusplus.com/reference/cstdio/vfprintf/
Siehe auch:
http://stackoverflow.com/questions/3672753/how-to-pass-variable-number-of-arguments-from-one-function-to-another

OsDevNewbie

  • Beiträge: 282
    • Profil anzeigen
    • YourOS Kernel
Gespeichert
« Antwort #5 am: 12. March 2013, 19:08 »
Was mir noch auffällt, ist, dass du int64_t bzw. uint64_t bei va_arg nutzt. Das ist bei 32-Bit-Code nicht korrekt.

Das ist schon richtig, das ist nämlich 64-Bit-Code. Hab ich vergessen zu erwähnen tut mir leid. Aber jetzt wisst ihr es ja  :-D
Viele Grüsse
OsDevNewbie

Ein Computer ohne Betriebsystem ist nicht mehr wert als ein Haufen Schrott.
Ein Computer ist eine Maschine, die einem Lebewesen das kostbarste klaut, was sie selber nicht hat:
DIE ZEIT DES LEBENS

OsDevNewbie

  • Beiträge: 282
    • Profil anzeigen
    • YourOS Kernel
Gespeichert
« Antwort #6 am: 19. March 2013, 19:21 »
Die optionalen Parameter vom printf können nicht einfach so an das fprintf weitergereicht werden. Du musst in printf das Zeug mit va_list arg; va_start ... machen, und das dann an eine Funktion (z.B. int vfprintf(FILE *, const char *, va_list arg);) übergeben, die dann die eigentlich Ausgabe macht. Beispiel hier: http://www.cplusplus.com/reference/cstdio/vfprintf/
Siehe auch:
http://stackoverflow.com/questions/3672753/how-to-pass-variable-number-of-arguments-from-one-function-to-another
Inwiefern hilft mir das jetzt weiter?
Ich habe es jetzt anders gemacht, so wie bei obigen Quelltext gezeigt , doch es funktioniert immer noch nicht. Der String wird nachwievor richtig ausgegeben, nur dann das eingesetzte für die Platz ist (glaube ich) ziemlicher Schrott.
Ich hoffe ihr könnt mir noch weiterhelfen.
Viele Grüsse
OsDevNewbie

Ein Computer ohne Betriebsystem ist nicht mehr wert als ein Haufen Schrott.
Ein Computer ist eine Maschine, die einem Lebewesen das kostbarste klaut, was sie selber nicht hat:
DIE ZEIT DES LEBENS

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #7 am: 19. March 2013, 19:47 »
Ich habe den Quellcode mal (unter Linux) ausprobiert und im Prinzip funktioniert er bei mir. Zwei Kleinigkeiten: Du hast ein mal putchar("%");statt putchar('%'); geschrieben, und dein puts ist nicht standardkonform. Das normale puts gibt am Ende immer einen Zeilenumbruch aus. Wenn dein puts das nicht tut, wirst du Probleme bekommen, wenn dein Compiler auf die Idee kommt einen Aufruf von printf zu optimieren, der mit \n endet. Und dann wunderst du dich, warum der Zeilenumbruch nicht funktioniert. Mein Vorschlag wäre, dass du die in vfprintf verwendete puts-Funktion anders nennst.

Vielleicht ist deine Implementierung von va_arg oder der itoa-Funktionen fehlerhaft.
Dieser Text wird unter jedem Beitrag angezeigt.

OsDevNewbie

  • Beiträge: 282
    • Profil anzeigen
    • YourOS Kernel
Gespeichert
« Antwort #8 am: 19. March 2013, 21:45 »
Also bei mir funktioniert es irgendwie nicht. Keine Ahnung warum nicht. Hier ist mal das Disassemble:
vfprintf():
//TODO: alle print-Funktionen fertigstellen
int vfprintf(FILE *stream, const char *format, va_list arg)
{
  10351c: 55                    push   %rbp
  10351d: 48 89 e5              mov    %rsp,%rbp
  103520: 48 83 ec 30          sub    $0x30,%rsp
  103524: 48 89 7d e8          mov    %rdi,-0x18(%rbp)
  103528: 48 89 75 e0          mov    %rsi,-0x20(%rbp)
  10352c: 48 89 55 d8          mov    %rdx,-0x28(%rbp)
uint64_t pos = 0;
  103530: 48 c7 45 f8 00 00 00 movq   $0x0,-0x8(%rbp)
  103537: 00
static char buffer[64];
//char *buffer = malloc(64); //Mehr wird momentan nicht benötigt
if(stream == stdout)
  103538: 48 8b 05 79 a1 18 00 mov    0x18a179(%rip),%rax        # 28d6b8 <stdout>
  10353f: 48 39 45 e8          cmp    %rax,-0x18(%rbp)
  103543: 0f 85 af 01 00 00    jne    1036f8 <vfprintf+0x1dc>
{
for(; *format; format++)
  103549: e9 99 01 00 00        jmpq   1036e7 <vfprintf+0x1cb>
{
switch(*format)
  10354e: 48 8b 45 e0          mov    -0x20(%rbp),%rax
  103552: 0f b6 00              movzbl (%rax),%eax
  103555: 0f be c0              movsbl %al,%eax
  103558: 83 f8 25              cmp    $0x25,%eax
  10355b: 0f 85 6b 01 00 00    jne    1036cc <vfprintf+0x1b0>
{
case '%': //Formatieren?
switch(*(++format))
  103561: 48 83 45 e0 01        addq   $0x1,-0x20(%rbp)
  103566: 48 8b 45 e0          mov    -0x20(%rbp),%rax
  10356a: 0f b6 00              movzbl (%rax),%eax
  10356d: 0f be c0              movsbl %al,%eax
  103570: 83 e8 25              sub    $0x25,%eax
  103573: 83 f8 54              cmp    $0x54,%eax
  103576: 0f 87 42 01 00 00    ja     1036be <vfprintf+0x1a2>
  10357c: 89 c0                mov    %eax,%eax
  10357e: 48 8b 04 c5 d0 81 10 mov    0x1081d0(,%rax,8),%rax
  103585: 00
  103586: ff e0                jmpq   *%rax
{
case 'u': //Unsigned int
utoa(va_arg(arg, uint64_t), buffer);
  103588: 48 83 45 d8 08        addq   $0x8,-0x28(%rbp)
  10358d: 48 8b 45 d8          mov    -0x28(%rbp),%rax
  103591: 48 83 e8 08          sub    $0x8,%rax
  103595: 48 8b 00              mov    (%rax),%rax
  103598: be e0 b0 20 00        mov    $0x20b0e0,%esi
  10359d: 48 89 c7              mov    %rax,%rdi
  1035a0: e8 87 06 00 00        callq  103c2c <utoa>
puts(buffer);
  1035a5: bf e0 b0 20 00        mov    $0x20b0e0,%edi
  1035aa: e8 29 05 00 00        callq  103ad8 <puts>
pos += strlen(buffer);
  1035af: bf e0 b0 20 00        mov    $0x20b0e0,%edi
  1035b4: b8 00 00 00 00        mov    $0x0,%eax
  1035b9: e8 73 12 00 00        callq  104831 <strlen>
  1035be: 48 98                cltq   
  1035c0: 48 01 45 f8          add    %rax,-0x8(%rbp)
break;
  1035c4: e9 01 01 00 00        jmpq   1036ca <vfprintf+0x1ae>
case 'i': //Signed int
case 'b':
itoa(va_arg(arg, int64_t), buffer);
  1035c9: 48 83 45 d8 08        addq   $0x8,-0x28(%rbp)
  1035ce: 48 8b 45 d8          mov    -0x28(%rbp),%rax
  1035d2: 48 83 e8 08          sub    $0x8,%rax
  1035d6: 48 8b 00              mov    (%rax),%rax
  1035d9: be e0 b0 20 00        mov    $0x20b0e0,%esi
  1035de: 48 89 c7              mov    %rax,%rdi
  1035e1: e8 4a 05 00 00        callq  103b30 <itoa>
puts(buffer);
  1035e6: bf e0 b0 20 00        mov    $0x20b0e0,%edi
  1035eb: e8 e8 04 00 00        callq  103ad8 <puts>
pos += strlen(buffer);
  1035f0: bf e0 b0 20 00        mov    $0x20b0e0,%edi
  1035f5: b8 00 00 00 00        mov    $0x0,%eax
  1035fa: e8 32 12 00 00        callq  104831 <strlen>
  1035ff: 48 98                cltq   
  103601: 48 01 45 f8          add    %rax,-0x8(%rbp)
break;
  103605: e9 c0 00 00 00        jmpq   1036ca <vfprintf+0x1ae>
case 'f': //Float
ftoa(va_arg(arg, double), buffer);
  10360a: 48 83 45 d8 08        addq   $0x8,-0x28(%rbp)
  10360f: 48 8b 45 d8          mov    -0x28(%rbp),%rax
  103613: 48 83 e8 08          sub    $0x8,%rax
  103617: f2 0f 10 00          movsd  (%rax),%xmm0
  10361b: 66 0f 14 c0          unpcklpd %xmm0,%xmm0
  10361f: 66 0f 5a c0          cvtpd2ps %xmm0,%xmm0
  103623: bf e0 b0 20 00        mov    $0x20b0e0,%edi
  103628: e8 b1 06 00 00        callq  103cde <ftoa>
puts(buffer);
  10362d: bf e0 b0 20 00        mov    $0x20b0e0,%edi
  103632: e8 a1 04 00 00        callq  103ad8 <puts>
pos += strlen(buffer);
  103637: bf e0 b0 20 00        mov    $0x20b0e0,%edi
  10363c: b8 00 00 00 00        mov    $0x0,%eax
  103641: e8 eb 11 00 00        callq  104831 <strlen>
  103646: 48 98                cltq   
  103648: 48 01 45 f8          add    %rax,-0x8(%rbp)
break;
  10364c: eb 7c                jmp    1036ca <vfprintf+0x1ae>
case 'X': //Hex 8
break;
  10364e: eb 7a                jmp    1036ca <vfprintf+0x1ae>
case 'x': //Hex 4
break;
  103650: eb 78                jmp    1036ca <vfprintf+0x1ae>
case 'y': //Hex 2
break;
  103652: eb 76                jmp    1036ca <vfprintf+0x1ae>
case 's': //String
{
char *temp = va_arg(arg, char*);
  103654: 48 83 45 d8 08        addq   $0x8,-0x28(%rbp)
  103659: 48 8b 45 d8          mov    -0x28(%rbp),%rax
  10365d: 48 83 e8 08          sub    $0x8,%rax
  103661: 48 8b 00              mov    (%rax),%rax
  103664: 48 89 45 f0          mov    %rax,-0x10(%rbp)
puts(temp);
  103668: 48 8b 45 f0          mov    -0x10(%rbp),%rax
  10366c: 48 89 c7              mov    %rax,%rdi
  10366f: e8 64 04 00 00        callq  103ad8 <puts>
pos += strlen(temp);
  103674: 48 8b 45 f0          mov    -0x10(%rbp),%rax
  103678: 48 89 c7              mov    %rax,%rdi
  10367b: b8 00 00 00 00        mov    $0x0,%eax
  103680: e8 ac 11 00 00        callq  104831 <strlen>
  103685: 48 98                cltq   
  103687: 48 01 45 f8          add    %rax,-0x8(%rbp)
}
break;
  10368b: eb 3d                jmp    1036ca <vfprintf+0x1ae>
case 'c': //Char
putchar((char)va_arg(arg, int32_t));
  10368d: 48 83 45 d8 04        addq   $0x4,-0x28(%rbp)
  103692: 48 8b 45 d8          mov    -0x28(%rbp),%rax
  103696: 48 83 e8 04          sub    $0x4,%rax
  10369a: 8b 00                mov    (%rax),%eax
  10369c: 0f be c0              movsbl %al,%eax
  10369f: 89 c7                mov    %eax,%edi
  1036a1: e8 11 04 00 00        callq  103ab7 <putchar>
pos++;
  1036a6: 48 83 45 f8 01        addq   $0x1,-0x8(%rbp)
break;
  1036ab: eb 1d                jmp    1036ca <vfprintf+0x1ae>
case '%': //%
putchar('%');
  1036ad: bf 25 00 00 00        mov    $0x25,%edi
  1036b2: e8 00 04 00 00        callq  103ab7 <putchar>
pos++;
  1036b7: 48 83 45 f8 01        addq   $0x1,-0x8(%rbp)
break;
  1036bc: eb 0c                jmp    1036ca <vfprintf+0x1ae>
default: //Ansonsten ungültig
format--;
  1036be: 48 83 6d e0 01        subq   $0x1,-0x20(%rbp)
pos--;
  1036c3: 48 83 6d f8 01        subq   $0x1,-0x8(%rbp)
break;
}
break;
  1036c8: eb 18                jmp    1036e2 <vfprintf+0x1c6>
  1036ca: eb 16                jmp    1036e2 <vfprintf+0x1c6>
default: //Ansonsten schreibe das aktuelle Zeichen
putchar(*format);
  1036cc: 48 8b 45 e0          mov    -0x20(%rbp),%rax
  1036d0: 0f b6 00              movzbl (%rax),%eax
  1036d3: 0f be c0              movsbl %al,%eax
  1036d6: 89 c7                mov    %eax,%edi
  1036d8: e8 da 03 00 00        callq  103ab7 <putchar>
pos++;
  1036dd: 48 83 45 f8 01        addq   $0x1,-0x8(%rbp)
uint64_t pos = 0;
static char buffer[64];
//char *buffer = malloc(64); //Mehr wird momentan nicht benötigt
if(stream == stdout)
{
for(; *format; format++)
  1036e2: 48 83 45 e0 01        addq   $0x1,-0x20(%rbp)
  1036e7: 48 8b 45 e0          mov    -0x20(%rbp),%rax
  1036eb: 0f b6 00              movzbl (%rax),%eax
  1036ee: 84 c0                test   %al,%al
  1036f0: 0f 85 58 fe ff ff    jne    10354e <vfprintf+0x32>
  1036f6: eb 08                jmp    103700 <vfprintf+0x1e4>
break;
}
}
}
else
pos = EOF;
  1036f8: 48 c7 45 f8 ff ff ff movq   $0xffffffffffffffff,-0x8(%rbp)
  1036ff: ff
//free(buffer);
return pos;
  103700: 48 8b 45 f8          mov    -0x8(%rbp),%rax
}
  103704: c9                    leaveq
  103705: c3                    retq   

printf():
int printf(const char *format, ...)
{
  1037b4: 55                    push   %rbp
  1037b5: 48 89 e5              mov    %rsp,%rbp
  1037b8: 48 81 ec d0 00 00 00 sub    $0xd0,%rsp
  1037bf: 48 89 b5 58 ff ff ff mov    %rsi,-0xa8(%rbp)
  1037c6: 48 89 95 60 ff ff ff mov    %rdx,-0xa0(%rbp)
  1037cd: 48 89 8d 68 ff ff ff mov    %rcx,-0x98(%rbp)
  1037d4: 4c 89 85 70 ff ff ff mov    %r8,-0x90(%rbp)
  1037db: 4c 89 8d 78 ff ff ff mov    %r9,-0x88(%rbp)
  1037e2: 0f b6 c0              movzbl %al,%eax
  1037e5: 48 8d 14 85 00 00 00 lea    0x0(,%rax,4),%rdx
  1037ec: 00
  1037ed: b8 1b 38 10 00        mov    $0x10381b,%eax
  1037f2: 48 29 d0              sub    %rdx,%rax
  1037f5: 48 8d 55 ff          lea    -0x1(%rbp),%rdx
  1037f9: ff e0                jmpq   *%rax
  1037fb: 0f 29 7a f1          movaps %xmm7,-0xf(%rdx)
  1037ff: 0f 29 72 e1          movaps %xmm6,-0x1f(%rdx)
  103803: 0f 29 6a d1          movaps %xmm5,-0x2f(%rdx)
  103807: 0f 29 62 c1          movaps %xmm4,-0x3f(%rdx)
  10380b: 0f 29 5a b1          movaps %xmm3,-0x4f(%rdx)
  10380f: 0f 29 52 a1          movaps %xmm2,-0x5f(%rdx)
  103813: 0f 29 4a 91          movaps %xmm1,-0x6f(%rdx)
  103817: 0f 29 42 81          movaps %xmm0,-0x7f(%rdx)
  10381b: 48 89 bd 38 ff ff ff mov    %rdi,-0xc8(%rbp)
va_list arg;
va_start(arg, format);
  103822: 48 8d 85 38 ff ff ff lea    -0xc8(%rbp),%rax
  103829: 48 83 c0 08          add    $0x8,%rax
  10382d: 48 89 85 40 ff ff ff mov    %rax,-0xc0(%rbp)
int pos = vfprintf(stdout, format, arg);
  103834: 48 8b 8d 38 ff ff ff mov    -0xc8(%rbp),%rcx
  10383b: 48 8b 05 76 9e 18 00 mov    0x189e76(%rip),%rax        # 28d6b8 <stdout>
  103842: 48 8b 95 40 ff ff ff mov    -0xc0(%rbp),%rdx
  103849: 48 89 ce              mov    %rcx,%rsi
  10384c: 48 89 c7              mov    %rax,%rdi
  10384f: e8 c8 fc ff ff        callq  10351c <vfprintf>
  103854: 89 85 4c ff ff ff    mov    %eax,-0xb4(%rbp)
va_end(arg);
return pos;
  10385a: 8b 85 4c ff ff ff    mov    -0xb4(%rbp),%eax
}
  103860: c9                    leaveq
  103861: c3                    retq   
Im Anhang ist noch ein Screenshot von meinen Ausgaben.
Die Ausgaben über die PCI-Devices erledige ich momentan über mehrere fprint()-Funktionen, da ich diese zum Debuggen benötige und es da deshalb ziemlich blöd wäre, wenn man die Zahlen nicht lesen könnte.
P.S.: Das mit dem puts und putch werde ich korrigieren. Danke für den Hinweis und danke für deine Bemühungen  :lol:.
Viele Grüsse
OsDevNewbie

Ein Computer ohne Betriebsystem ist nicht mehr wert als ein Haufen Schrott.
Ein Computer ist eine Maschine, die einem Lebewesen das kostbarste klaut, was sie selber nicht hat:
DIE ZEIT DES LEBENS

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #9 am: 20. March 2013, 00:07 »
Wenn ich mir den Screenshot so anschaue hab ich einige andere Verdächtige als printf im Sinn.

Einmal ist da ein Problem mit den Umlauten. Das ö in "grösste" scheint nicht richtig kodiert zu sein. Du kannst entweder deinen Editor dazu bringen den Quelltext in Codepage 437 zu speichern, oder du verzichtest auf Umlaute.

Diese zufälligen Zeichen in weiß auf grau, die nahe der Mitte liegen, können von was anderem als der printf-Funktion stammen. Mir fällt auf, dass diese nur in den Zeilen auftreten, in denen du etwas Farbiges ausgibst. Möglicherweise funktionieren die Funktionen dafür nicht richtig. Oder diese Zeichen waren schon vorher da, und die Funktion für die Ausgabe von normalem Text übermalt diese Zeichen.

Es folgt ein wenig Spekulation: Deine Ausgabefunktion für Zeichen geht möglicherweise nicht korrekt mit unsigned char/char um. Das weiß auf grau bedeutet, dass dass Attributbyte auf 0x7f (eigentlich 0xff, aber manche Emulatoren ignorieren das Blinken) gesetzt ist. Das passiert zum Beispiel, wenn man den Videospeicher als short-Pointer anspricht. Das hat zur Folge, dass wenn man ein char in den Videospeicher schreibt, dieser entsprechend seines Vorzeichens auf 16-Bit erweitert wird. Eine Lösung wäre in der Funktion für Ausgabe von einzelnen Zeichen das auszugebene Zeichen auf unsigned char zu casten bevor du es in den Videospeicher schreibst.

Die ausgegebenen Zahlen bezüglich des Speicherverbrauchs und der PCI-Geräte sind etwas komisch, aber ich würde da nicht auf ein Problem mit der printf-Funktion schließen, sondern eher die Berechnung dieser Zahlen überprüfen. Das System scheint 1 GB RAM zu haben, was nicht abwegig ist. Die 2 Millionen PCI-Geräte sind offensichtlich falsch, aber wenn du in der Nähe von Adresse 0x20A63D nichts besonderes machst, dann würde ich da erstmal nicht fprintf verdächtigen. (Und wenn du an dieser Adresse was hast und der PCI-Code korrekt ist, dann würde ich den Stack bzw. va_arg verdächtigen.)

Aber um das Problem wirklich einzugrenzen, musst du alle Seiteneffekte eliminieren. Du solltest alle Ausgaben in deinem Code ausschalten (bzw. so viele Dinge wie möglich deaktivieren), und ausschließlich printf und die Ausgabefunktionen testen. Wenn es keine äußeren Einflüsse gibt, sollte das Debugging dieser Funktionen wesentlich einfacher sein. Ich würde vorschlagen, dass du ein paar einfache Ausgaben wie printf("%i %s %c\n", 123, "456", '7'); machst, um den Fehler einzugrenzen.
« Letzte Änderung: 20. March 2013, 00:11 von Jidder »
Dieser Text wird unter jedem Beitrag angezeigt.

Svenska

  • Beiträge: 1 792
    • Profil anzeigen
Gespeichert
« Antwort #10 am: 20. March 2013, 00:34 »
Du gibst die PCI-Vendor-ID dezimal aus, die wird aber üblicherweise hexadezimal dargestellt.
32902 = 0x8086 = Intel (diverses)
5549 = 0x15ad = VMware (Grafikkarte, diverses)
4096 = 0x1000 = LSI Logic (SCSI-/SATA-Controller)
4724 = 0x1274 = Ensoniq (Soundkarte)
Sieht sinnvoll aus. Damit scheint dein fprintf zu funktionieren.

edit: offensichtlich habe ich eben das Problem verpeilt. Ignoriere diesen Post dann bitte. :-)
« Letzte Änderung: 20. March 2013, 00:36 von Svenska »

OsDevNewbie

  • Beiträge: 282
    • Profil anzeigen
    • YourOS Kernel
Gespeichert
« Antwort #11 am: 21. March 2013, 19:02 »
Hallo,
Wörter, die Umlaute enthalten schreibe ich anfangs immer mit Umlauten, bis mir auffällt, dass diese ja gar nicht möglich sind. Ist also schon gefixt worden, nach der Aufnahme des Screenshots.

Also das mit der Farbkodierung hat sich wie folgt ergeben: Ich hatte bei meiner Ausgabefunktion, das auszugebende Zeichen als char definiert. GCC hat dieses Zeichen in das Register cx geladen, dabei werden aber die oberen 16 Bit nicht gelöscht. Er führt danach folgende Operation aus:
or %edx,%ecx
In edx steht der Farbcode drin und zwar um 8 Bit nach links verschoben. Durch diese OR-Operation wurden auch immer die unteren 4 Bit von dh gesetzt, da in ecx zufällig genau diese Bits gesetzt waren. Diesen Fehler habe ich jetzt dadurch gefixt, dass ich die Variabel, die das Zeichen enthält als unsigned char definiert habe.

Also die Zahlen bezüglich des Speichers und der PCI-Geräte werden über folgenden Syntax ausgeben (hier für die PCI-Geräte):
setColor(BG_BLACK | CL_LIGHT_GREY);
printf("  Bus ");
printf(itoa(pciDevice->Bus));
printf(",Slot ");
printf(itoa(pciDevice->Slot));
printf(": Vendor ");
printf(itoa(pciDevice->VendorID));
printf(",Classcode ");
printf(itoa(pciDevice->ClassCode));
printf(",Subclass ");
printf(itoa(pciDevice->Subclass));
printf(",ProgIF ");
printf(itoa(pciDevice->ProgIF));
printf(",Header ");
printf(itoa(pciDevice->HeaderType));
printf(",IRQ ");
printf(itoa(pciDevice->irq));
printf("\n");
Ich mache die Ausgabe so, da ich die Zahlen lesen wollte und die printf-Funktion diese nicht richtig ausgibt. Die itoa-Funktion ist diesselbe, die auch printf benutzt und sie funktioniert auch richtig, also die Parameter die übergeben werden, werden richtig umgewandelt.

Warum sollen die PCI-Geräte falsch sein? Und was hat es mit der Adresse 0x20A63D auf sich?

Sonst danke für deine Hilfe, du hast mich ja trotzdem auf einen Fehler hingewiesen ;)
Viele Grüsse
OsDevNewbie

Ein Computer ohne Betriebsystem ist nicht mehr wert als ein Haufen Schrott.
Ein Computer ist eine Maschine, die einem Lebewesen das kostbarste klaut, was sie selber nicht hat:
DIE ZEIT DES LEBENS

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #12 am: 21. March 2013, 20:25 »
Am unteren Bildschirmrand steht "2132709 Geraete gefunden". Das klingt nicht richtig. Der Wert davon in hexadezimal ist 0x20A63D, was durchaus eine potentielle Adresse für Code oder Daten ist, wenn du irgendwelche Tutorials mehr oder weniger befolgt hast. Meine Vermutung ist, dass dieser Wert auf dem Stack liegt, und von der printf-Funktion anstelle des richtigen Parameters genommen wird. Wenn das so ist, würde das auf ein Problem mit va_arg hindeuten. Deswegen habe ich vorgeschlagen, dass du mal nur die printf-Funktion testest.
Dieser Text wird unter jedem Beitrag angezeigt.

Svenska

  • Beiträge: 1 792
    • Profil anzeigen
Gespeichert
« Antwort #13 am: 21. March 2013, 23:03 »
Ich würde dir übrigens vorschlagen, längere Strings für Ausgaben zu benutzen. Also für deine PCI-Zeile etwa in der Art:

printf("\tBus: %u.%u: Vendor 0x%x, Class %u, Subclass %u, ProgIF %u, Header %u, IRQ %u\n",
   pciDevice->Bus, pciDevice->Slot, pciDevice->VendorID, pciDevice->classCode,
   pciDevice->Subclass, pciDevice->ProgIF, pciDevice->HeaderType, pciDevice->irq);


Das ist im Code deutlich besser lesbar und man erkennt auf Anhieb, wie die Bildschirmdarstellung aussieht und kann den Text später noch vernünftig ändern. Außerdem kann printf() selbst Zahlen umwandeln.

Wenn du das so machst, könnte sich daraus übrigens ergeben, dass dein printf() doch kaputt ist.

Gruß,
Svenska

OsDevNewbie

  • Beiträge: 282
    • Profil anzeigen
    • YourOS Kernel
Gespeichert
« Antwort #14 am: 22. March 2013, 20:33 »
Wenn du das so machst, könnte sich daraus übrigens ergeben, dass dein printf() doch kaputt ist.
Aber wenn ich es so mache, dann gibt es eben auch nur Schrott als Zahlen aus. Also ich glaube die Zahlen, die so ausgeben werden stimmen so. Wenn ich es aber eben auf diese Art mache, dann kommen auch wieder nur solche hohen Zahlen raus.
Viele Grüsse
OsDevNewbie

Ein Computer ohne Betriebsystem ist nicht mehr wert als ein Haufen Schrott.
Ein Computer ist eine Maschine, die einem Lebewesen das kostbarste klaut, was sie selber nicht hat:
DIE ZEIT DES LEBENS

Svenska

  • Beiträge: 1 792
    • Profil anzeigen
Gespeichert
« Antwort #15 am: 22. March 2013, 21:49 »
Nunja, "wenn ich es so mache", "dann gibt es", "Schrott als Zahlen", "ich glaube", "auf diese Art", "hohe Zahlen" - geht es auch etwas konkreter? Ich habe genau garkeine Ahnung, was du wie machst, in welchen Fällen es nicht funktioniert (und in welchen Fällen dann doch), was genau nicht funktioniert und wie sich der Fehler äußert.

Auch nicht, nachdem ich deinen Beitrag gelesen habe.

Also: Wenn printf("A: "); printf(itoa(num)); printf("\n"); funktioniert, aber printf("A: %u\n", num); nicht, dann ist deine printf-Implementation kaputt und sollte zuerst repariert werden. Danach kann man über weitere Dinge reden.

OsDevNewbie

  • Beiträge: 282
    • Profil anzeigen
    • YourOS Kernel
Gespeichert
« Antwort #16 am: 23. March 2013, 02:54 »
Tut mir leid für meinen verwirrenden Kommentar.
Du hast mein Problem aber trotzdem richtig interpretiert.
Wegen meiner printf-Funktion, das ist eben das Problem, ich weiss nicht woran es liegt. Deshalb ist oben ja der Quellcode und das Disassembly davon gepostet.
Aber trotzdem Danke für deine bisherige Hilfe.
Viele Grüsse
OsDevNewbie

Ein Computer ohne Betriebsystem ist nicht mehr wert als ein Haufen Schrott.
Ein Computer ist eine Maschine, die einem Lebewesen das kostbarste klaut, was sie selber nicht hat:
DIE ZEIT DES LEBENS

MNemo

  • Beiträge: 547
    • Profil anzeigen
Gespeichert
« Antwort #17 am: 23. March 2013, 10:27 »
Wie sehen den deine va_arg-Makros aus?
Die sollten auf die builtins von GCC verweisen, da Parameter bei AMD64 nicht alle auf dem Stack landen, und die Makros etwas komplizierter werden.
[edit]Ok. Dem disassmblierten code zufolge verwendest du wohl die richtigen Makros[/edit]

Abgesehen davon verwendest du nicht die selben Funktionen um Zahlen in strings zu verwandeln.
itoa(int, char[])    // printf
/* bzw. */
utoa(unsigned int, char[]);
/* vs. */
itoa(int)            // Ausgabe der PCI-Geräte

[edit]
Ich kann sonst nichts fehlerhaftes finden und würde wie folgt vorgehen.
  • in der vprintf statt der zahl erst mal "INT" ausgeben, um zu gucken ob der Code überhaupt ausgeführt wird.
  • überprüfen ob der richtige parameter wert ankommt, printf("%u", 1337); und in der vprintf if(va_arg(…) == 1337) puts("OK"); else puts("Fail");
« Letzte Änderung: 23. March 2013, 10:49 von MNemo »
„Wichtig ist nicht, besser zu sein als alle anderen. Wichtig ist, besser zu sein als du gestern warst!“

OsDevNewbie

  • Beiträge: 282
    • Profil anzeigen
    • YourOS Kernel
Gespeichert
« Antwort #18 am: 29. March 2013, 19:41 »
Also ich der Code der vfprintf-Funktion erkennt diese Flags ("%u", "%i", usw.) richtig und führt auch den entsprechenden Code aus.
Aber eben nur irgendwie kommen als Argumente nicht die richtigen Werte rüber. Also bei einem Beispiel war es zum Beispiel so, dass an der Adresse dann die Adresse stand :?.
Ich habe gemerkt, dass die printf-Funktion, die ja vfprintf() aufruft, irgendwie die falsche Adresse für arg übergibt. Ich weiss nicht woran das liegen könnte und wie man dies Eventuell beheben könnte.
Viele Grüsse
OsDevNewbie

Ein Computer ohne Betriebsystem ist nicht mehr wert als ein Haufen Schrott.
Ein Computer ist eine Maschine, die einem Lebewesen das kostbarste klaut, was sie selber nicht hat:
DIE ZEIT DES LEBENS

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #19 am: 29. March 2013, 19:47 »
Ich habe gemerkt, dass die printf-Funktion, die ja vfprintf() aufruft, irgendwie die falsche Adresse für arg übergibt. Ich weiss nicht woran das liegen könnte und wie man dies Eventuell beheben könnte.
Wie sehen den deine va_arg-Makros aus?
Jetzt wäre die richtige Zeit diese Frage zu beantworten ;)
Dieser Text wird unter jedem Beitrag angezeigt.

 

Einloggen