asm-Programm als Unterprogramm in C aufrufen(Visual Studio)
-
Hallo!
Ich habe ein kleines asm-Programm geschrieben, das in meinem C-Programm als separates Unterprogramm aufgerufen werden soll.
Das asm-Programm leistet folgendes: Es soll in der Call-by-Value aus C übergebenen Variable(32Bit, Int) die Anzahl der Einser zählen und sie in die C-Variable Anzahl(32Bit,Int,Call-by-Reference) abspeichern./* main.c */ #include "fkt.asm" extern void anzahl(int,int*); int main(void){ int a = 10; int Anzahl; anzahl(a,&Anzahl); printf("%d\n\n",Anzahl); system("PAUSE"); return 0; }
;fkt.asm public _anzahl .model small .code _anzahl proc near push ebp mov ecx,32 mov ebp,esp mov ebx,[ebp+8] mov eax,[ebp+12] m: rol eax,1 adc [ebx],dword ptr 0 loop m pop ebp ret _anzahl endp end
Leider wird mir mein Konstrukt von VS08 mit 3 Fehlermeldungen quittiert:
Error 1 error C2061: syntax error : identifier '_anzahl'
Error 2 error C2059: syntax error : ';'
Error 3 error C2059: syntax error : '.'Weiß einer Rat?
-
Ich habs auch schon mit GCC probiert. Dort sagt er mir folgendes:
expected '=', ',', ';' 'asm' or '__attribute__' before '_anzahl'
-
und wenn du den assembler code in eine funktion schreibst?
funktioniert es dann?
hab noch nie aus einer datei direkt assemblercode in C geladen
-
Du meinst eine C-Fkt erstellen und dort meine ASM-Fkt als Inline-Assembler impementieren?
Eigentlich wollte ich gerade das nicht tun. Es geht nämlich darum, ein ASM-Unterprogramm zu erstellen, dieses dann in C aufzurufen und den Compiler automatisch alle übergebenen Variablen auf den Stack vom Asm-Unterprogramm bringen zu lassen.
-
Hallo!
Ich habs jetzt nochmal mit GCC probiert, und zwar folgendermaßen:
//prog1.c #include <stdlib.h> #include <stdio.h> __attribute__((cdecl)) extern void anzahl(int,int*) ; int main(){ int a=10; int b=0; anzahl(a,&b); printf("%d",b); return 0; }
;asm1.asm segment .text global anzahl anzahl: enter 0,0 pusha mov ecx,32 mov ebx,[ebp+4] mov eax,[ebp+8] m: rol eax,1 adc DWORD [ebx],0 loop m popa leave ret
asm1.asm ich mit NASM compiliert:
nasm -f elf asm1.asm
prog1 mit gcc:
gcc -c prog1.c
Wenn ich die beiden .o - Dateien aber miteinander verbinden will:
g++ -o proggi prog1.o asm1.o
bekomm ich diese Fehlermeldung:
PROG1.o: In function
main': PROG1.C: (.text+0x2d): undefined reference to
anzahl(int, int*)'
collect2: ld returned 1 exit statusJemand eine Idee?
-
Du musst Funktionen/Sprungmarken in anderen Modulen als extern deklarieren. Das hast Du getan.
Wahrscheinlich liegt es daran, dass du deiner Funktion einen falschen Namen gegeben hast. C/C++ erwartet, dass deren Name mit einem Unterstrich beginnt! Also muss die Funktion in ASM _anzahl heißen.
Vorsicht: in C den Unterstrich am Namensanfang NICHT mitaufrufen. Das macht der Compiler automatisch. Also den Aufruf so lassen. Einfach mal ausprobieren.
-
Übrigens gibt es ein GNU Programm nm (als Teil der binutils), mit dem man sich alle Symbole in einer Objektdatei anschauen kann. In diesem Fall:
nm prog1.o
Listet alle definierte und undefinierte Symbole in der Objektdatei prog1.o auf.
nm asm1.o
Das gleiche noch mal für asm1.o. Damit kann mal sehen, was der Linker sieht und warum die eine oder die andere Referenz für ihn undefiniert ist...
-
Hallo nochmal!
ASM als separates Unterprogramm habe ich nun hinbekommen.
Allerdings bin ich nun auch schon wieder auf ein weiteres Problem gestoßen...
Folgendes wollte ich programmieren:
In C werden 2 char arrays erstellt (array1 und array2). Das erste array wird initialisiert und mit dem '\n'-Zeichen terminiert.
Beide Arrays werden an das ASM-Unterprogramm übergeben, welches die Zeichen in umgekehrter Reihenfolge im array2 abspeichert.Bsp.:
array1 = abcd
array2 = dcba#include <stdio.h> #include <stdlib.h> extern void strmirror(char*,char*); int main(void){ int i,status; char c; char buf_in[256] = {'\n'}; char buf_out[256] = {'\n'}; printf("Bitte geben Sie einen Satz ein: (max. 256 Zeichen)\n"); for(i=0;i<256 && (c = (unsigned char)getchar()) != EOF && c != '\n'; i++) buf_in[i] = c; printf("\n\n"); strmirror(&buf_in[0],&buf_out[0]); printf("Das Ergebnis ist: %s\n",buf_out); status = 0; return status; }
Das Unterprogramm durchläuft zunächst das array1 solange, bis das Terminierungszeichen '\n' auftaucht und zählt dabei im ECX die Anzahl der Zeichen ungleich '\n'.
Im nächsten Schritt werden einfach alle Zeichen in umgekehrter Reihenfolge ins array2 kopiert, wobei die Anzahl der zu kopierenden Zeichen im ECX steht.segment .text global strmirror %define String_in [ebp+8] %define String_out [ebp+12] strmirror: enter 0,0 pusha mov eax,String_in mov ebx,String_out mov ecx,0 m2: cmp byte[eax],10D je m inc ecx inc eax jmp m2 m: sub eax,1 mov dl,[eax] mov [ebx],dl inc ebx loop m popa leave ret
Mein Problem: Als Ausgabe bekomme ich das hier auf den Schirm
Das Ergebnis ist: 1315=DIP_GNIRYEK_EMONG
Segmentation faultIch vermute den Fehler im Vergleich cmp byte[eax],10D.
Kriege aber dennoch keine Lösung zustande.
-
Ich habs doch hinbekommen.
Die Frage ist nun folgende:
Ich lasse mir in C das Zeichen '\n' dezimal ausgeben und bekomme 10 raus.
Frag ich in Assembler ab, ob ein Array-Element den Wert 10 bzw. 0AH hat, spinnt mein Programm.
Wie kommt das denn?Achchso, wieso geht folgendes nicht:
in eax befindet sich eine Adresse von einer 32-Bit-Variable
in ebx befindet sich eine Adresse von einer 32-Bit-VariableDann spuckt mir
mov dword [eax],[ebx]
einen Fehler aus.
Hat es einen tieferen Sinn, dass sowas nicht geht?
Ich mein, warum muss ich denn enbedingt eine Variable in den Prozessor laden?