# Assembler/C crossover



## BassBox (13. März 2011)

Hallo.
Ich möchte programme für mein eigenes os in c schreiben. Jetzt habe ich das problem wie übergebe ich parameter von c in assembler? Ich verwende den TC (Turbo C(++))
BSP:

kernel.c

```
extern "C" void setpixel(int p1,int p2,int p3);
...
setpixel(4,8,16);
```

assembykernel.asm

```
global setpixel
setpixel:
 ?
```

Wie übertrage ich die parameter p1, p2 und p3 in assemmbler universalregister?

Vielen Dank im Voraus
LG
BassBox


----------



## sheel (13. März 2011)

Hi

die Parameter kannst du dir vom Stack holen.
Wie genau, hängt von der Aufrufkonvention ab (cdecl, stdcall...).
Die regelt auch, wohin der Returnwert gehört.

Welche dein Compiler verwendet, kann man einstellen (bzw. dort nachschauen)

Gruß


----------



## BassBox (13. März 2011)

Danke!  Kannst du mir die Typen erklären? Ich nimm dann den der am besten zu nutzen ist. Das coole am TC ist das der einen guten Inlineassembler hat so dass ich einfach C Befehle mit Assembler ohne externe Date definieren kann. Was ich auch noch gerne wissen wollte welchen linker ich nehmen sollte. Ich würde den TC + linker zu einem Paket zusammenschnüren und dann meinen Freunden geben die schon lange an meinem oder Programme für mein OS entwickeln wollen, da ich schon recht weit gekommen bin.
vielen Dank
LG
Euer BassBox


----------



## sheel (13. März 2011)

Bei Inline-Asm brauchst du dich normalerweise nicht um die Parameterübergabe kümmern, weil der Compiler das durch den C-Funktionskopf dazugeneriert.

Jedenfalls hat die engl. Wikipedia einen schönen Artikel dazu, und die wichtigsten Aufrufkonv. gibts auch in Deutsch: http://de.wikipedia.org/wiki/Aufrufkonvention

Für die verbreitesten (cdecl und stdcall) wäre das im Prinzip bei zB einer Funktion
int funk(int a, int b, int c)

*cdecl: Ausserhalb der Funktion, wo sie aufgerufen wird:*
1)Mit push die Parameter in den Stack schieben.
Hier liegt auch der auffälligste Unterschied zw. stdcall und cdecl: Die Reihenfolge.
cdecl braucht die Parameter "verkehrt":

```
push cwert
push bwert
push awert
```
Bei stdcall ist die Reihenfolge a,b,c.

2)Mit call die Funktion aufrufen

3) Die Parameter wieder aufräumen.
Bei 3 int (also 12 Byte) kann man das zB so machen:

```
add esp, 12
```

Der Rückgabewert kann jetzt auch aus eax abgeholt werden.

*cdecl: In der Funktion:*
Soll man generell nur eax, ecx und edx verwenden.
ebx ... ist reserviert.

1)Die Parameter muss man sich in Reihenfolge a,b,c mit pop vom Stack abholen.
2)Irgendwann eax setzen und returnen.

*stdcall: Ausserhalb der Funktion, wo sie aufgerufen wird:*
1)Mit push die Parameter in den Stack schieben.
Hier "normale" Reihenfolge
	
	
	



```
push awert
push bwert
push cwert
```

2)Mit call die Funktion aufrufen

3) Die Parameter NICHT wieder aufräumen.
Das muss hier die Funktion machen

Returnwert gleich wie bei cdecl.

*stdcall: In der Funktion:*
Ziemlich gleich wie bei cdecl.
1) Die Pop-Parameter sind aber in verkehrter Reihenfolge.
2) Statt "add esp, 12" außerhalb der Funktion bei cdecl gibt man den 12er hier beim Befehl ret mit.

```
ret 12
```

Gruß


----------



## BassBox (13. März 2011)

vielen Dank! Wie läuft das dann über den Inlineassembler? Kann ich dann einach die Parameter dann als Vartiable ansprechen? Und wie mache ich dann da die Rückgabe? Welche linker hälst du eigentlich für sowas geeignet? Ich danke dir vielmals wenn ich mal wieder mit dem Pc und nicht mit tutsmobile online bin danke ich dir für die Hilfe !!

Lg
BassBox

Ps: Hast du ein eigenes Os? Wenn ja was kann es?


----------



## sheel (13. März 2011)

BassBox hat gesagt.:


> Wie läuft das dann über den Inlineassembler? Kann ich dann einach die Parameter dann als Vartiable ansprechen? Und wie mache ich dann da die Rückgabe?




```
#include<stdio.h>

int _cdecl funk(int a,int b,int c)
{
	int xx;
	_asm
	{
		mov eax, a
		add eax, b
		add eax, c
		mov xx, eax
	}
	return xx;
}

int main()
{
	int x;
	x=funk(1,2,3);
	printf("%d",x);
	return 0;
}
```

Geht einfach so. Ist zwar Visual-Studio-Syntax, sollte sich aber nicht großartig unterscheiden.

Zum _cdecl bei funk: So kann man auch unabhängig von den globalen Einstellungen die CallingConv. für einzelne Funktionen festlegen.
Ist aber hier nicht nötig (bzw. funktioniert mit stdcall genauso), weil die Parameterübergabe/Rückgabe ja vom Compiler übernommen wird.



BassBox hat gesagt.:


> Welche linker hälst du eigentlich für sowas geeignet?


Jeden...mein Zeug mach ich mit NASM bzw. inline mit Visual Studio, als Linker bei beiden den von Microsofts VS.



BassBox hat gesagt.:


> Ps: Hast du ein eigenes Os? Wenn ja was kann es?


Ja/nicht viel.
Hab es hauptsächlich zum Lernen bzw. Ausprobieren gemacht, und weniger damit es am Schluss funktioniert.
Dadurch ist es an allen Ecken eine Baustelle, die vorläufig aus Zeitmangel eingefroren ist.

Gruß


----------



## BassBox (13. März 2011)

Mein Os ist mein Hobby. Ich entwickle mit 5 Freunden an dem Ding und ich schreibe immer Treiber, das Hauptsystem und den Editor und den Rest teilen wir auf. Es ist echt super und ich hoffe das dadraus noch was wird. Es kann Dateien von einer FAT16 Platte und von einer FAT12 Diskette lesen, unterstützt die Dateiformate .COM .bmp .txt .bin


----------



## sheel (13. März 2011)

Das klingt ja schon ganz ordentlich...nur weiter so


----------



## BassBox (13. März 2011)

sorry das ich die antwort nicht vertig schreiben konnte. Mein Akku war leer... Hier ist der Rest

das Os hat einen Maus Treiber und den ANSI Zeichensatz implementiert und  noch ein paar System eigene recurcen.
Das Komplette os hat eine mit der Maus zu bedienende GUI, Ein Bild editor und ausgabeprogramm, einen Editor  mit Drucker Funktionen (leider nur über den Paralelen Port), einen DOS Emulator welcher eine DOS 2.0 Umgebung emuliert un natürlich einen grafischen Filemanager. Also das ist denke ich mal nich schlecht.
Vielen Dank für deine Hilfe
BassBox


----------



## BassBox (15. März 2011)

Nochne frage: Funktioniert das ganze auch bei C++ ? 
(sorry für das doppelt posting aber ich kann die frage einfach nicht in die letzte antwort reinpacken)


----------



## sheel (15. März 2011)

Das mit den Aufrufkonventionen?
Ja, warum nicht?

Etwas wichtiges muss man aber beachten: Klasseninterne Methoden haben eine eigene CC:
thiscall
Der Grund: Die Methoden werden zuerst unabhängig vom tatsächlichen Objekt kompiliert und bekommen dann beim Aufruf einen Pointer auf das betroffene Objekt als zusätzlichen "Parameter" mit.

thiscall ist zu allem Überfluss auch noch je nach Compiler anders.

Bei Visual Studio, wenn die Funktion eine fixe Parameteranzahl hat:
Wie stdcall, die Objektadresse muss aber vor dem Aufruf in ECX rein.

Bei Visual Studio, wenn die Funktion variable Parameterlistenlängen hat:
Wie cdecl die Objektadresse muss auch hier vor dem Aufruf in ECX rein.

Bei gcc:
Wie cdecl, die Adresse wird aber wie ein normaler Parameter mit den anderen in den Stack geschoben.
Und zwar als letztes push (bzw. im C++-Quelltext wäre das der erste Parameter).

Gruß


----------



## BassBox (15. März 2011)

und per Inlineassembler? Gleich wie mit c oder? Ich habe gehört das man um globale vartiablen setzten zu können irgendwas einstellen musst. Ich nutze übrigen auch in diesem Fall den Turbo C(++). Hat eigentlich jeder Hochsprachen Compiler einen Inline Assembler?
Könnte ich dann auch rein theorethisch in Java weier schreiben? Ich habe nach geguckt:  der Inlineassembler vom TC heist BASM
vielen Dank für deine Hilfe
Lg
BassBox


----------



## sheel (15. März 2011)

BassBox hat gesagt.:


> und per Inlineassembler? Gleich wie mit c oder?


Ja.



BassBox hat gesagt.:


> Ich habe gehört das man um globale vartiablen setzten zu können irgendwas einstellen musst.


Keine Ahnung. Bei Visual Studio gehts jedenfalls ohne zusätzliche Einstellungen.



BassBox hat gesagt.:


> Hat eigentlich jeder Hochsprachen Compiler einen Inline Assembler?


Die mir bekannten C/C++-Compiler alle. Vielleicht schreibt es ja auch der Sprachstandard vor...
Aber jede Hochsprache generell? Nein.
zB Bei solchen Halb-Interpretersprachen wie C# und Java würde das überhaupt keinen Sinn machen.
Die haben ja eigene Exe-Formate, in denen keine direkten Prozessorbefehle vorkommen.
Wohin also mit dem übersetzten Assemblerteil?



BassBox hat gesagt.:


> Könnte ich dann auch rein theorethisch in Java weier schreiben?


Du könntest Inline-Asm in einer C-DLL machen und diese per JNI/JNA in Java verwenden.



BassBox hat gesagt.:


> Ich habe nach geguckt:  der Inlineassembler vom TC Geist BASM


Das B steht wahrscheinlich für Borland.

Gruß


----------



## BassBox (16. März 2011)

Danke! Gut ich habe noch eine Frage. Um mir die mühe und dem Umweg mit dem Linker zu ersparen kann ich das zeugs nich einfach ganz normal zu exe machen und das programm dann mit einem Jump oder Call starten? Ich weis nicht genau ob exe gleich funktioniert wie binary oder noch einen header hat.
Hast du Zufällig ahnung davon? Wäre nämlich besser das zeugs zu exe zu machen und dann zu starten als noch über umwege zu linken. Ich würde das starten nähmlich lieber dem OS überlassen (ist Praktischer und das programm wird unwesentlich kleiner).(hat leder nicht viel mit dem thema zu tun aber ich wills trotztdem wissen) Und Weist du ob die Dos interupts (realmode) auch unterwindows 32bit in der IDT eingetragen sind? Und ob es irgendwo im netzt eine tabelle mit den windows idt interrupts gibt? (ich versuche mein OS linux und Windows Kompartibel zu halten)
LG
BassBox


----------



## sheel (17. März 2011)

Zu Exe machen kannst du schon, aber auch ein ganz normales Hello-World-Programm unter Windows wird gelinkt.
Hier die "normalen" Parameter, die VS unter 32bit-XP bei mir für ein Konsolenprogramm nimmt:

```
kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /incremental:no /pdb:"Release/prog.pdb" /machine:I386 /out:"Release/prog.exe"
```
Also ziemlich viele Standardlibrarys von Windows mit drin.
Alle werden vielleicht nicht gebraucht, aber wenn du eine Standard-Exe von Windows starten können willst, musst du die Funktionen alle zur Verfügung stellen.

Und ja, eine Exe hat auch ihr eigenes Format. Wie das aufgebaut ist, kann man schnell im Internet finden.

Gruß


----------



## BassBox (17. März 2011)

Also ich möchte exe nur verwenden da ich mir sparen will irgendwelche eigenen compiler zusammenschrauben will sonderen das es für den programmiere leicht sen soll schnell einen ausführbare datei zu bekommen. Wie entfernt man die windows bibliotheken aus der exe? Bzw wie verhindert mann das sie eingebunden werden? Und nein ich werde noch keine Windows-Funktionen Definiren sonderen es so machen: Man includiert die datei OS.h in welcher Die befehle  mit assembler Definiert sind (natürlich unter nutztung von Pmode Interruptions). Man schreibt ein Programm mit den Definierten Befehlen von der OS.h compiliert das und startet es dann unter meinem eigenem os. Die datei soll ohne windowsfunktionen verwendet werden . Ich habe mir hier angeguckt wie exe aufgebaut ist, aber ich check jetzt nicht welche tabelle wo hingehört und wo die jetzt zu finden ist. 
Danke für deine Hilfe und unterstütztung
LG
BassBox


----------



## sheel (17. März 2011)

Libs entfernen: Je nach Linker durch CMD-Parameter.
1) Einfach keine Extra-libs angeben
2) Ggf. je nach Linker einen Parameter, dass keine Standardlibs verwendet werden sollen.

Bei Projekten von grafischen IDEs wird die Kommandozeile automatisch mitgeneriert, muss dann in den Projekteinstellungen nachträglich angepasst werden.

Bei Winprogs wirst du allerdings Probleme bekommen.
Ohne min. die kernel32.dll läuft nichts. Auch kein Linker.
Grund: Der Einstiegspunkt/Startpunkt eines Windows-Programms ist in Wirklichkeit nicht main, sondern eine interne Funktion aus der kernel.dll.
Ohne die und ihren Einstiegspunkt linkt überhaupt nichts.

Zumindest die Grundzüge der Windows-Prozessverwaltung wirst du implementieren müssen, wenn du nicht schon abgeschreckt bist.

Zum EXE-/PE-Format: Den "ToDo´s" zufolge ist der Artikel auf der Lowlevelseite unvollständig.
Warum nicht gleich die offizielle Spec?
http://msdn.microsoft.com/en-us/windows/hardware/gg463119.aspx
Nach dem Zustimmen zur Lizenz bekommt man eine docx-Datei.

Gruß


----------



## BassBox (17. März 2011)

ok. Weist du was ich mache das jetzt so: ich nehme jetzt den binary linker und bastle mir ein eigenes executables dateformat. Und um den einstuegspunkt zu kriegen bastle ich mir ne eigene Lib zusammen die ich dann nutze anstatt der von Windows um den einstuegspunkt zu kriegen. Bei der Nächsten Version meines OS befasse ich mich ernsthaft mit der kompatibilität zu Microsoft Programmen. Setzt der TC beim Installieren irgendwelch Reg Einträge? Ich will den zu nem eigenem installet umbauen. (darf ich ja weil das Copyright ausgelaufen ist und Borland zwischendurch pleite gegangen ist.) 
LG
Danke für deine Unterstütztung
BassBox


----------



## sheel (18. März 2011)

"Binary Linker"? Nie gehört.
Und denkst du nicht, dass der mit einem eigenen Format nicht zurecht kommen wird?


Zu den TC-Reg-Einträgen: Denk schon. Warum schaust du nicht nach?
Und Borland ist doch von irgendwem übernommen worden?
Ich glaube nicht, dass das CRight automatisch weg ist.

Gruß


----------



## BassBox (18. März 2011)

Ich meine Das Anderst: Ich nehme einen linker der zu bin linkt. Ich habe das jetzt so:
kernel.c wird mit einer obj datei zusammen gelinkt die eine externe Main Funktion aufruft:
	
	
	



```
[Bits 32] 		
extern _main 	;definiert externe main funktion
global start 	;globale startmarke
start:
call _main 	    ;rufe die main funktion in c kernel auf.
int 17h         ;springe zurück (system eigene funktion)
```

Da die beiden Programme noch objekt dateien sind, sind die globalen labels noch verfügbar.
Das funktioniert jetzt einwand frei.

Ich verwende jtzt den Djgpp den ich dan als paket an meine freunde gebe, mit nem installer Batch sktipt welches dan auch meine headder und linker skripte mitgibt.
Dane für deine Hilfe
BassBox


----------



## BassBox (20. März 2011)

Kennst du einen 32bit linker für den tc der zu binary linkt? Ich brauche dringend einen! 
LG
BassBox


----------

