[C/asm] ungewöhnlich grosser string argv[1]
-
Mosche an alle:
Es gibt mal wieder etwas das ich mir nicht selbst erklären kann:D :
Wenn ich aus meinem C code#include <stdio.h> #include <string.h> int strlen_f(char*); int main(int argc, char** argv) { int erg = strlen_f(argv[1]); printf("%i", erg); printf("\n"); return 0; }
...das erste argument (argv[1]) an eine Assembler funktion übergebe, die die länge des Strings berechnen soll, erhalte ich eine mir unerklärlich hohe zahl.
Bei z.b "test" als erstes argument, lautet die Ausgabe : 1579
Hier der ASM code der mit dem C programm gelinkt wird:.globl strlen_f .type strlen_f, @function strlen_f: enter $0, $0 movl $-3, %eax #counter movl 8(%ebp), %ebx #catch parameter leave .lo: inc %eax inc %ebx #search for term byte(0) cmp $0, (%ebx) #if found: jmp ret jne .lo ret: ret #ret strlen
Bei der Übergabe eines in main() declarierten cStrings funktioniert alles so wie es sollte.
Nur bei der übergabe eines arguments bekomme ich eine Falsche ausgabe.Bin für jede Erklärung dankbar
Gruss darrel
-
enter/leave ist hier reichlich überflüssig, du prüfst erst ab dem zweiten Zeichen und wieso fängt dein counter bei -3 statt 0 an?
Das Hauptproblem dürfte allerdings darin bestehen, dass deine Funktion ebx verändert, bei cdecl-Konvention darf eine Funktion nur eax,ecx und edx verändern.
-
camper schrieb:
enter/leave ist hier reichlich überflüssig, du prüfst erst ab dem zweiten Zeichen und wieso fängt dein counter bei -3 statt 0 an?
Das Hauptproblem dürfte allerdings darin bestehen, dass deine Funktion ebx verändert, bei cdecl-Konvention darf eine Funktion nur eax,ecx und edx verändern.danke erstmal für die schnelle Antwort.
Ich habe jetzt enter/leave entfernt, den counter auf 0 gesetzt, ebx mit edx getauscht und den vergleich an den anfang der schleife gesetzt
.type strlen_f, @function strlen_f: movl 4(%esp), %edx movl $0, %eax lo: cmp $0, (%edx) inc %edx inc %eax jne lo ret: ret
....und bekomme jetzt ein segmention fault
-
inc verändert das Zero-Flag. Deine Schleife endet also erst, wenn eax überlauft - dann hast du allerdings bereits den gesamten Speicher durchsucht, der doch teilweise geschützt sein dürfte.
-
camper schrieb:
inc verändert das Zero-Flag. Deine Schleife endet also erst, wenn eax überlauft - dann hast du allerdings bereits den gesamten Speicher durchsucht, der doch teilweise geschützt sein dürfte.
Ich habe jetzt "inc" mit "addl $1" ersetzt, was ja das selbe ist bis darauf, dass das zero flag gesetzt wird.
aber ich erhalte immernoch einen segmention fault
-
Die CDECL Calling Convention nicht vergessen
; prologue
push ebp
mov ebp,esp; code
; epilogue
pop ebp
ret
-
Darrel schrieb:
camper schrieb:
inc verändert das Zero-Flag. Deine Schleife endet also erst, wenn eax überlauft - dann hast du allerdings bereits den gesamten Speicher durchsucht, der doch teilweise geschützt sein dürfte.
Ich habe jetzt "inc" mit "addl $1" ersetzt, was ja das selbe ist bis darauf, dass das zero flag gesetzt wird.
aber ich erhalte immernoch einen segmention fault
inc beeinflusst alle normalen Flags außer carry. add beeinflusst zusätzlich das carry-Flag. mit jne prüfst du den Status, des zero-flags - dessen Inhalt hängt aber nunmal vom ergebnis der letzten Operation ab, die dieses Flag verändert, und das ist bei dir inc, und inc durch add zu ersetzen, bringt natürlich überhaupt nichts.
Was du möchtest, ist das Ergebnis des Vergleichs als Sprungbedingung zu nutzen - dann musst du durch entsprechende Anordnung der Befehle folglich dafür sorgen, dass sich das Flag zwischen Vergleich und Sprung nicht mehr ändern kann. Es gibt noch die Möglichkeit, zum Inkrementieren lea einzusetzen, lea beeinflusst keine Flags. Das ist aber nicht unbedingt sinnvoll.
.type strlen_f, @function strlen_f: movl 4(%esp), %eax lo: incl eax cmpb $0, -1(%eax) jne lo subl 4(%esp), %eax dec eax ret
könnte zum Beispiel funktionieren.
-
Vielen dank für die Aufklärung !
Jetzt ist mir alles um einiges klarer