Autor Thema: Parameter für meine API-Funktionen  (Gelesen 3045 mal)

bitmaster

  • Troll
  • Beiträge: 1 138
    • Profil anzeigen
    • OS-64 = 64 Bit Operating System
Gespeichert
« am: 18. October 2006, 18:00 »
Hallöchen!

Im Moment übergebe ich meinen API Funktionen die Parameter über Register (z.B. rax, rbx, .. rsi, rdi ... r8, r9 etc.). Aber damit sind meine API Funktionen nicht sehr gut in Hochsprachen wie C/C++ anzusprechen. Ich kenne mich ja wie ihr alle wisst nicht so gut in Hochsprachen aus. Aber ich möchte das meine API Funktionen auch Beispielsweise mit C++ angesprochen werden können. Meine API Funktionen sind ja nichts anderes wie Interruptaufrufe. In rax wird eine Nummer übergeben (z.B. 0 für ShowCursor) und in den anderen Register halt Parameter. Das ganze habe ich in einem Makro gepackt, damit man sich die Nummern in rax nicht merken muss. Also z.B. kann man meine ShowCursor Funktion jetzt so aufrufen:

mov rcx,Wert ;Y-Position
mov rdx,Wert ;X-Position
mov bl,Wert ;Taste
ShowCursor ;ruft Makro auf

Das Makro macht folgendes:

push rax
xor rax,rax
int 30h
pop rax

Der Handler des "int 30h" prüft dann den rax Wert und springt zur ShowCursor unterfunktion. Diese ließt dann die Werte von bl, rcx und rdx aus und blablabla.

So verändert die Makrofunktion auch keine Register, sonst würde der ASM Programmierer ja auswendiglernen müssen welche Register verändert werden und diese vorher abspeichern müssen.

Das Ganze ist natürlich nicht sehr Hochsprachenfreundlich (da es dort diese Register ja nicht gibt). Mein Problem ist jetzt, wie mache ich die Parameterübergabe so das sie auch für Hochsprachen vernünftig ist. Ich habe da an den Stack gedacht. Man könnte es doch so realisieren, oder? :

push Wert ;X-Wert
push Wert ;Y-Wert
push Wert ;Taste
ShowCursor ;das Makro könnte ja bleiben, schließlich kann man das C/C++ doch durch *.h Dateien erklären, oder?

Dann würde man zum "int 30h" springen. Dieser würde den rax Wert prüfen und in diesem Beispiel zur Unterfunktion ShowCursor springen. Dann könnte man es doch so machen:

ShowCursorPrg:
push alle Register ;speichere alle Registerwerte die von ShowCursorPrg verändert werden
mov rbp,rsp
mov rbx ,[ss:rsb+blabla] ;hole z.B. den Wert für die Taste und kopiere ihn nach rbx

Würde das Sinn machen? Ich habe gesehen Windows API Funktionieren so ähnlich (nur das ein call aufgerufen wird und kein int). Ich könnte ja dann ShowCursorPrg dazu bringen die Rücksprungadressen in Variablen zu Speichern (und den RFlags-Register-Wert). Dann die den Stack so verkleinern das die Werte nicht nacher noch vom Stack geholt werden müssen. Bei Windows müssen diese z.B. nacher auch nicht mehr vom Stack geholt werden. Und die Windows API kann man ja super mit C/C++ ansprechen. Wäre das dann eine gute Lösung?

Wie sieht es dann aber mit Werten aus die ich von einer API Funktion bekomme und nicht gebe (also Z.B. eine Funktion wie ReadTime die mir dann ja die Zeit ausgeben muss, wo soll die die Zeit reinspeichern)?

Hoffentlich versteht ihr was ich meine.

thx

bitmaster
In the Future everyone will need OS-64!!!

__OS_coder

  • Beiträge: 69
    • Profil anzeigen
Gespeichert
« Antwort #1 am: 18. October 2006, 18:23 »
Also ich würde es ja folgendermaßen realisieren:

Du schreibst dir ein Headerfile das folgendermaßen aussieht:

#ifndef __HEADER_H_
#define __HEADER_H_

void ShowCursor( unsigned x, unsigned y, char Taste );

#endif


Dann das dazugehörige Sourcefile:

#include "./header.h"

void ShowCursor ( unsigned x, unsigned y, char Taste ) {
    __asm__ __volatile__ ( " movq %%rcx, %0\n"
                           " movq %%rdx, %1\n"
                           " movb %%bl, %2\n"
                           " int $0x30\n"
                          : : "m"(y), "m"(x), "m"(Taste) :
                          );
}


Als Beispiel für C jetzt. Dann würdest du das Sourcefile kompilieren
und zu einer Shared Library oder einer Static Library machen, die
dann zu dem C Programm hinzugelinkt werden muss. Und das
Headerfile benutzt du dazu, um die Funktionen dem Quelltext des
C Programms bereitzustellen.

Die Cursor-Funktion ließe sich dann so in einem C-Programm
verwenden:

#include "header.h"

int main() {
    ShowCurser( 2, 2, TASTE );
    return 0;
}


Aber ich denke, dass du das genau so realisieren willst, nicht?
Nur du programmierst die Funktion für das C-Programm in ASM.
Aber das brauchst du ja gar nicht, wenn du GCC-Inline ASM benutzt
geht das viel bequemer... dann musst du dich nicht um die
Adressen der Parameter auf dem Stack scheren... das macht der GCC
dann für dich.


bitmaster

  • Troll
  • Beiträge: 1 138
    • Profil anzeigen
    • OS-64 = 64 Bit Operating System
Gespeichert
« Antwort #2 am: 18. October 2006, 18:42 »
@__OS_coder: Das heißt also, ich brauche das mit dem Stack garnicht machen da man C/C++ auch beibringen kann mit Register umzugehen (halt vom Anwendungsprogrammierer versteckt)? Das wäre ja noch besser.

Zitat
Nur du programmierst die Funktion für das C-Programm in ASM.
Ich möchte ja auch das man eine Makrodatei für Assembler hat um auch mit Assembler meine API ansprechen zu können. Ich möchte halt nur in Assembler programmieren. Aber da nicht alle so sind wie ich, möchte ich auch das es möglich ist meine API z.B. mit C/C++ anzusprechen.

thx

bitmaster
In the Future everyone will need OS-64!!!

bluecode

  • Beiträge: 1 391
    • Profil anzeigen
    • lightOS
Gespeichert
« Antwort #3 am: 18. October 2006, 18:46 »
@__OS_coder: Das heißt also, ich brauche das mit dem Stack garnicht machen da man C/C++ auch beibringen kann mit Register umzugehen (halt vom Anwendungsprogrammierer versteckt)?
Das kommt aber auch auf den compiler dann an. Das was __OS_coder gepostet hat kompiliert imho auch nur mit dem gcc.
Ich hab es bei meinem OS genauso realisiert wie __OS_coder...
lightOS
"Überlegen sie mal 'nen Augenblick, dann lösen sich die ganzen Widersprüche auf. Die Wut wird noch größer, aber die intellektuelle Verwirrung lässt nach.", Georg Schramm

__OS_coder

  • Beiträge: 69
    • Profil anzeigen
Gespeichert
« Antwort #4 am: 20. October 2006, 15:32 »
In der Tat das kompiliert nur GCC... Allerdings braucht der
Anwendungsprogrammierer nicht unbedingt GCC benutzen...
Wenn du das Sourcefile mit GCC kompilierst, kannst du daraus
ja ne Static Library machen, die dann zu dem Programm des
Anwendungsprogrammierers hinzugelinkt wird. Da ist es egal, ob
der Anwendungsprogramierer GCC oder BorlandC oder sonst
irgendeinen Compiler verwendet.

Das Headerfile versteht jeder C Compiler...

;)

 

Einloggen