Autor Thema: printf-dirt  (Gelesen 2144 mal)

BBIQ

  • Beiträge: 2
    • Profil anzeigen
Gespeichert
« am: 17. March 2010, 14:38 »
Hi,

Ich bin dabei eine printf-Funktion zu schreiben (gcc, x86) und hab mich in der ersten Version an das "Standardvorgehen" gehalten, also va_arg() usw zu benutzen um auf die Funktionsparameter zuzugreifen.
Jetzt will ich die Aufrufe aber sparen, indem ich einfach per Zeiger durch den Stack reise und die Argumente dort ganz direkt aufsammle.
Wenn die printf-Fkt als erstes diesen Pointer deklariert und ihm dann seine eigene Adresse zuweist, weiß man ja wo im Stack er steht und wie weit man nach oben rutschen muss um bei den Aufrufargumenten von printf landet. Spart auf jeden Fall Funktionsaufrufe (naja, ein paar wenigstens).

Ich wollte mal fragen, ob ich irgendwas übersehe was mir bei diesem Vorgehen später das Leben schwer machen könnte.

In meinem Beispiel wurde damit aus:
int kprintf(char *f_str, ...) {
va_list args;
va_start(args, 0xffffffff);
int count = 0;
while ( f_str[count] != '\0' ) {
if ( f_str[count] == '%' )
switch ( f_str[++count] ) {
case '\0': { putc('\0'); return 0; }
case '%' : { putc('%'); putc('%'); break; }
case 'x': { hex(va_arg(args, unsigned int)); break; }
[...]

das:
int kprintf_dirty(char *f_str, ...) {
unsigned long *arg_ptr;
arg_ptr = (unsigned long*)&arg_ptr+6;
int count = 0;
while ( f_str[count] != '\0' ) {
if ( f_str[count] == '%' )
switch ( f_str[++count] ) {
case '\0': { putc('\0'); return 0; }
case '%' : { putc('%'); putc('%'); break; }
case 'x': { hex(*arg_ptr++); break; }

danke schonmal

bluecode

  • Beiträge: 1 391
    • Profil anzeigen
    • lightOS
Gespeichert
« Antwort #1 am: 17. March 2010, 15:07 »
Ich wollte mal fragen, ob ich irgendwas übersehe was mir bei diesem Vorgehen später das Leben schwer machen könnte.
Sobald du das portieren willst, hast du verloren. Bei x64 geht es ganz sicher nicht so einfach, da teilweise die Argumente in Registern liegen.

Außerdem sehe ich nicht wie du dir Funktionsaufrufe sparst. Die va_* Sachen sind Compiler-Builtins und werden normalerweise nicht in Funktionsaufrufe umgewandelt, sondern der Code (der genau das gleiche wie du macht) wird eben dort eingefügt.
lightOS
"Überlegen sie mal 'nen Augenblick, dann lösen sich die ganzen Widersprüche auf. Die Wut wird noch größer, aber die intellektuelle Verwirrung lässt nach.", Georg Schramm

BBIQ

  • Beiträge: 2
    • Profil anzeigen
Gespeichert
« Antwort #2 am: 17. March 2010, 15:29 »
Danke, da war mir bis eben nicht klar was compiler-builtin genau bedeutet ;).
Ich dachte eben dass der Code in Form eines zusätzlichen Funktionsaufrufs ausgeführt wird um auf die einzelnen Argumente zuzugreifen.

Das mit der Portierung schwante mir schon ein bisschen, auch wenn ich nicht wusste wo der Haken dabei genau ist.

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #3 am: 17. March 2010, 16:07 »
Du kannst dir den erzeugten Code ja mal mit objdump anschauen.

Auf jeden Fall ist es eine schlechte Idee, von der korrekten Implementierung auf einen Hack umzustellen. ;)
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

 

Einloggen