2011-01-13 7 views
27

Ich versuche, eine Funktion in Assembly zu verwenden, die von einem C-Projekt aufgerufen wird. Diese Funktion soll eine libc-Funktion aufrufen, sagen wir printf(), aber ich bekomme immer einen Segmentierungsfehler.Aufruf von Assembly-Funktionen von c

In der C-Datei ich die Erklärung der Funktion des

int do_shit_in_asm() 

In der .asm Datei

.extern printf 
.section .data 
     printtext: 
       .ascii "test" 
.section .text 
.global do_shit_in_asm 
.type do_shit_in_asm, @function 

do_shit_in_asm: 
    pushl %ebp 
    movl %esp, %ebp 
    push printtext 
    call printf 
    movl %ebp, %esp 
    pop %ebp 
ret 

Alle Zeiger Kommentare geschätzt würde ich sagen lassen.

as func.asm -o func.o 

gcc prog.c func.o -o prog 
+23

+1 für Funktionsname –

+33

"Alle Zeiger würden geschätzt werden": int * ptr; – Sapph

+0

@Sapph +1 aber es hilft nicht :)) –

Antwort

16

ändern push printtext zu push $printtext.

Wie es ist, laden Sie einen Wert von der Adresse printtext und drängen Sie, anstatt die Adresse zu schieben. Daher übergeben Sie 'test' als 32-Bit-Nummer anstelle eines Zeigers, und printf versucht, dies als eine Adresse und Absturz zu interpretieren.

9

Eine der besten Möglichkeiten, um mit Assembler-Sprache-Funktionen, um loszulegen ist eine ähnliche Funktion in C, zu schreiben und bauen es dann mit dem Compiler-Schalter, der eine Assembler-Liste (-S auf gcc) erzeugt. Dann können Sie die Ausgabe dessen, was der Compiler getan hat, untersuchen und nach Bedarf modifizieren.

Dies ist besonders nützlich, wenn Sie Funktionen wie printf aufrufen, die eine andere Aufrufkonvention verwenden (wegen der variablen Anzahl von Argumenten). Der Aufruf dieser Funktionen kann sich von dem Aufruf von Nicht-Varargs-Funktionen unterscheiden.

+1

Sehr pädagogisch ... aber auch normalerweise sehr irreführend Das reale Problem ist die ABI spezifischen Details, welche Register bewahrt werden müssen, was sie bedeuten, und wie sie mit dem C ABI zusammenwirken ging diesen Pfad zuerst nach unten und dann erkannte, dass meine Assembly nicht besser wäre als was der Compiler erzeugen würde, was genau das Gegenteil von dem war, was ich erreichen wollte! – bbum

2

Danach:

push printtext 
call printf 

Sie wollen:

addl $4, %esp 

Weitere Erläuterungen:

Weil Sie x86 Linux verwenden gehe ich davon aus, die Aufrufkonvention des Angerufenen zur Reinigung erfordert Die Parameter. Weil Sie einen Zeiger vor dem Aufruf von printf gedrückt haben, ist Ihr Stack um 4 nach der ret Anweisung dieser Funktion deaktiviert.

Update:

Ja, OK, ich wurde verwendet, um Intel-Syntax, damit ich die Reihenfolge der Argumente nach hinten in meinem Kopf zu bekommen. Eigentlich ist das Fehlen der addl zurück zu esp egal, weil Sie esp korrekt in der Nähe Ihrer ret wiederherstellen. Meine nächste Vermutung ist, dass der Zeichenfolge Sie vorbei an printf ist eine Null-Terminator fehlen ... Lassen Sie mich sehen, was gas tut ...

Update 2:

OK, beendet gas null Strings Sie, ich denke, meine zweite Ahnung war falsch. Es sieht so aus, als ob du das Problem gefunden hast, also ist der Punkt strittig.

+0

immer noch Segmentierungsfehler –

+0

Ich wurde verwirrt, weil ich an die Intel-Syntax gewöhnt bin , nicht AT & T. Sie wollen eigentlich 'addl $ 4,% esp' Halten Sie, lassen Sie mich einen anderen Blick ... – asveikau

+0

@void - Vielleicht können Sie in einem Hex-Editor einchecken Zeichenfolge, die Sie an printf übergeben, wird null beendet? – asveikau

6

das Problem war, dass ich

pushl printtext 

eher, dass

pushl $printtext 

Vielen Dank allen für Ihre Hilfe und sorry für Ihre Zeit verschwenden mit wurde: P

+1

Sie haben es, bevor ich gepostet. Glückwunsch zur Lösung Ihres Problems. :-) –