2016-05-04 14 views
2

Ich möchte eine Funktion in Assembler von c aufgerufen werden, die ein Byte (Char) in die Datei schreiben wird. Hier ist, wie Funktion in c aussehen sollte:Schreibe Byte in Datei mit X86 Assembler

void writebyte (FILE *f, char b) 
{ 
    fwrite(&b, 1, 1, f); 
} 

Und hier ist der Code, dass es nennen:

#include <stdio.h> 

extern void writebyte(FILE *, char); 

int main(void) { 
    FILE *f = fopen("test.txt", "w");  
    writebyte(f, 1); 
    fclose(f); 
    return 0; 
} 

Bisher kam ich mit folgenden Assembler-Code auf:

.global  writebyte 
writebyte: 
    pushl %ebp 
    movl %esp, %ebp #standard params 
    pushl 12(%ebp) # pushing byte to the stack 
    pushl $1 
    pushl $1 
    pushl 8(%ebp)  #file to write 
    call fwrite 
    popl %ebp 
    ret 

Ich bekomme immer von gdb:

Program terminated with signal SIGSEGV, Segmentation fault. 
#0 0xffa9702c in ??() 

Wie schreibe ich eine solche Funktion in Assembly?

EDIT: Ich bin mit Ubuntu 16.04

+1

Wie Sie Bibliothek mit Assembler nicht haben std haben, dann wird der Code OS-abhängig sein. – Matt

+0

Ich benutze Ubuntu 16.04 – polyx

+5

Der erste Parameter beim Aufruf von fwrite ist eine Adresse, die auf das Byte zeigt, nicht das Byte selbst; Wenn Sie davon ausgehen, dass Sie das Programm korrekt verknüpft haben, erhalten Sie höchstwahrscheinlich einen seg-Fehler, da fwrite versucht, Ihr Byte als Adresse zu verwenden und auf Speicher zuzugreifen, die nicht in Ihrem virtuellen Adressraum zugeordnet sind. –

Antwort

3

Nach cdecl Konvention, sollten Sie die Argumente in umgekehrter Reihenfolge drücken. So sollte f zuerst gehen und b sollte zuletzt gehen. Auch der Stack sollte vom Anrufer nach dem Anruf fwrite() aufgeräumt werden.

Wie in den Kommentaren notiert, wird b als Wert empfangen, aber wir müssen es an fwrite() als Zeiger übergeben. Der Zeiger ist gleich dem Wert ebp + 12.

Dies scheint für mich zu arbeiten:

.global writebyte 
writebyte: 
    //create new stack frame 
    pushl %ebp 
    movl %esp, %ebp 

    //push the four arguments to stack (in reverse order) 
    pushl 8(%ebp) 
    pushl $1 
    pushl $1 

    //get pointer of "b" argument (%ebp+12) and move it to %eax 
    leal 12(%ebp), %eax 
    pushl %eax 

    //call fwrite() 
    call fwrite 

    //remove arguments from stack and pop %ebp 
    leave 

    ret 
+0

Warum verwenden Sie Unterstreichung in Call- und Funktionsname? – polyx

+1

Da ich dieses Beispiel mit Windows kompiliert habe und GCC unter Windows benötigt, müssen die Symbolnamen mit einem Unterstrich beginnen und allen C-Funktionen Unterstriche vorangestellt werden. Sie können das sehen, wenn Sie eine kompilierte Objektdatei zerlegen. Aber unter Linux sollten die Unterstriche nicht benötigt werden, also werde ich den Beitrag bearbeiten, um sie zu entfernen. –

+0

danke, gut zu wissen. – polyx

Verwandte Themen