Lowlevel
Lowlevel => Lowlevel-Coding => Thema gestartet von: BBIQ 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
-
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.
-
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.
-
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. ;)