C und Assembler
-
Hallo,
in deinem C-Programm liesst du zwei integer Werten ( 32bit) ein, und versuchst an Assembler-Procedur zu übergeben. In deinem Assembler-Modul deklarierst du aber zwei 16bit-Variablen. db = Define Byte, was nur einem Byte
entspricht.
Also du versuchst zwei 32bit Werten in 8bit Variablen zu packen, und das geht natürlich nicht.Deklarriere die einfach als DWORD und zwar so:
ZAHL1 dw ? ; Define WORD
ZAHL2 dw ? ; Define WORDGrüße
Peter
-
ausserdem musst du den erweiterten RET befehl benutzen, da du parameter auf den stack pushst, diese müssen wieder runter vom stack sonst wird mit ret die falsche rücksprung adresse geladen, dein programm springt also ins nirgendwo und stürzt ab. wenn du also 2 word parameter hast dann musst du RET 4 benutzen. die 4 steht für 4 byte die vom stack gepopt werden (2 worte = 4 byte).
-
Nein, nur wenn er es mit pascal convetion (__stdcall) deklariert, was er aber nicht hat.
-
Moin, Moin...
@PeterIII:
Das Programm ist wohl für DOS geschrieben. Unter DOS sind int-Werte 16 Bit breit und nicht 32 Bit!!!!
Du möchtest C und Assembler gemeinsam nutzen, dann musst Du auch die Konventionen einhalten. Die Variablen in dem Assemblermodul zu definieren, ist schlechter Stil. Die Parameter für die Funktion werden über den Stack übergeben und nicht nach Deiner Methode.
Meine Lösung:
#include <stdio.h> unsigned int addier(unsigned int, unsigned int); int main(void) { unsigned int var_a, var_b, summe; printf("Bitte ersten Wert eingeben:\n"); scanf("%d",&var_a); printf("\nBitte zweiten Wert eingeben:"); scanf("%d",&var_b); summe = addier(var_a, var_b); printf("\nDie Summe lautet: %d", summe); return 0; }
Das Assemblermodul:
; ; tasm /zn /ml modul.asm ; IDEAL DOSSEG MODEL SMALL ; STACK 100h -> unnötig CODESEG PUBLIC _addier PROC _addier NEAR push bp mov bp,sp ; Stackrahmen wurde erzeugt push bx ; Der Aufbau des Stacks: ; bp + 0 -> bp (gesichert durch obiges push bp) ; bp + 2 -> Rücksprungadresse (nur Offset, wg. Speichermodell SMALL) ; bp + 4 -> 1. Parameter der Funktion addier ; bp + 6 -> 2. Parameter der Funktion addier ; ; C legt die Parameter einer Funktion von rechts nach links auf ; den Stack. ; Die RUFENDE Funktion muss den Stack wieder aufräumen!!!! ; Nicht, wie wasily vorschlägt, ret 4 benutzen!!!! mov ax, [bp + 4] ; 1. Parameter vom Stack holen mov bx, [bp + 6] ; 2. Parameter vom Stack holen add ax, bx pop bx mov sp, bp pop bp ret ENDP _addier END
Die Namen der Variablen und der Funktion habe ich klein geschrieben. Daher muss das Assemblermodul auch mit der Option /ml(case sensitiv) assembliert werden.
Getestet habe ich alles mit Borland Turbo C++ 2.0. Lief ohne Probleme!
Ciao...
-
Danke erstmal alle zusammen,
@Kal El
Sehe ich es dann richtig, dass der Wert, der zuletzt in AX steckt als Rückgabewert der Funktion gilt?
-
Wie übergebe ich denn dann z.B. einen "long int" Wert?
Den muss ich ja über zwei Register verteilen...
Z.B. DX:AX oder so...
-
Genau so ist es auch.
Solche Sachen probier ich am liebsten einfach mit dem C Compiler aus. Ich schreib mir eine Funktion
long a() { return 0x12345678L; }
oder so und schau mir den erzeugten Code an. Daraus wird meistens recht schnell klar, wie man's machen muss.
-
Noch ein Nachtrag:
Du kannst auf den Unterstrich vor dem Funktionsnamen verzichten, wenn Du in der MODEL-Direktive die Sprache angibst(also C) für die das Modul gedacht ist.
MODEL SMALL, C
Der Assembler stellt die Unterstriche dann automatisch voran.
Ciao...
-
Hallo mal wieder =),
ich komme einfach nicht dahinter wie ich in Assembler zwei "long int" Werte addieren kann. Zuerst dachte ich, dass ich die 4 Byte Werte nacheinander vom Stack hole und in Variablen(double word) packe und diese anschließend addiere. Leider ist mir dann durch ein Buch aufgefallen, dass "add" mit zwei Speicherstellen nicht gehen soll. Wie macht man das denn nun am besten?
Und noch eine Frage: Falls ich mir einen Teil des "long int" Wertes (2 Byte) vom Stack hole und diesen nun in eine "variable (4 Byte)" Zwischenspeichern möchte, wie stelle ich dass an?
Mit "mov variable,[word ptr bp+4]" geht es nicht. Da meckert mein Compiler nurCIAO
-
Addieren, alles am Stack. Die richtigen offsets musst du dir dann schon selber anschauen.
mov ax,[bp+4] mov dx,[bp+6] add ax,[bp+8] adc dx,[bp+10] mov [bp+12],ax mov [bp+14],dx
word ptr [bp+4] ist die richtige Syntax. Aber ein Befehl kann immer nur einen Speicheroperand verwenden.
EDIT:
Wenn du eine Funktion
long addlong(long a, long b) { return a+b; }
geschrieben und den Code angeschaut hättest, wärest du da wahrscheinlich auch selber draufgekommen.