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 toanzahl(int, int*)'
    collect2: ld returned 1 exit status

    Jemand 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 fault

    Ich 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-Variable

    Dann 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?


Anmelden zum Antworten