Theoretiosch unendlich lange Zahlen berechnen / DLL Programiersprachen zur Verfügung

Biehler

BiehlerProductions
ID: 89792
L
4 Mai 2006
1.948
181
Hallo
ich bin gerade dabei eine Bibliothek zu schreiben, mit der man theoretisch unendlich lange Zahlen berechnen kann.
Diese Bibliothek soll nach meinen Planungen jede Menge mathematische Funktionen enthalten.
(Gut, bisher besteht nur eine Funktion :LOL: :ugly: )

Ich schreibe diese in Win32 Assembler, möchte aber gerne erreichen, dass Programmierer jeder Sprache diese benutzen können.
Dazu muss ich ja für jeden Aufrufstandard eine eigene Funktion einbauen.
Z.b. für die C-Aufrufkonvention, Pascal, etc.
Wieviel solcher Standards gibt es eigentlich, bzw. wieviel muss ich einbauen, damit ich ein breites Spektrum von allen Programmiersprachen habe?
Und vor allem:
In welchem Register muss in Pascal/Delphi ein Ergebnis zurückgegeben werden?
Und in welchem Register in C?
Ich weis, dass normalerweise das (E)AX Register in C verwendet wird.
Aber irgendwo hatte ich was gelesen, dass je nach bearbeitenden Datentyp ein anderes Register verwendet wird?

Und wie kann ich diese DLL für PHP verfügbar machen, bzw. geht das überhaupt?

Und @Linux
Angenommen ich verwende innerhalb der DLL keine einzige WinAPI Funktion, arbeite aber sonst ganz normal mit Assembler, kann diese Bibliothek dann auch auf Linux exportiert werden, ohne dass der Code geändert werden muss?

Und dann noch nebenbei:
Mich würd einfach mal interessieren, ob ihr jemals Zahlen größer als 4294967295 bearbeiten musstet.
 
Biehler schrieb:
Und dann noch nebenbei:
Mich würd einfach mal interessieren, ob ihr jemals Zahlen größer als 4294967295 bearbeiten musstet.
Selten, aber ich hab mich schon damit abgemüht :mrgreen:
 
ne dll ist standardisiert... da brauchst du dir kein kopf drüber machen welche register in welcher sprache in irgendner form verwendet werden. das wäre der fall wenn du das ganze als inline assembler umsetzen würdest, aber willst du ja nicht.
du musst nur irgendwie dein assembler code so compilieren das da ne dll rauskommt und schon kannst du mit jeder programmiersprache die dlls unterstützt das ganze über von dir festgelegte funktionsnamen aufrufen. (aber keine ahnung wie das in assembler genau aussieht, ich bin froh wenn ich ein paar buchstaben mit assembler ausgegeben bekomme :D)

bzgl php... sicher geht das. dazu musst du nen wrapper um deine bibliothek bauen der das extension interface von php implementiert. (das würde ich dann aber nicht in assembler versuchen :roll: )
 
ZeroCCC schrieb:
bzgl php... sicher geht das. dazu musst du nen wrapper um deine bibliothek bauen der das extension interface von php implementiert. (das würde ich dann aber nicht in assembler versuchen :roll: )
Für PHP würde ich mir gar nicht die Mühe machen. Wozu was Externes verwenden, wenn BC Math schon eingebaut ist?
 
tleilax schrieb:
Für PHP würde ich mir gar nicht die Mühe machen. Wozu was Externes verwenden, wenn BC Math schon eingebaut ist?

ja ich weiß das es dafür schon lösungen gibt... und nicht nur bc math. Aber ich geh mal davon aus das biehler das ganze als "übung" sieht, weil für dieses gebiet gibts in "jeder" sprache schon fertige lösungen.
 
ZeroCCC schrieb:
ja ich weiß das es dafür schon lösungen gibt... und nicht nur bc math. Aber ich geh mal davon aus das biehler das ganze als "übung" sieht, weil für dieses gebiet gibts in "jeder" sprache schon fertige lösungen.

Ja, die DLL dann in PHP einzubinden, ist mehr eine Übung.

ne dll ist standardisiert... da brauchst du dir kein kopf drüber machen welche register in welcher sprache in irgendner form verwendet werden. das wäre der fall wenn du das ganze als inline assembler umsetzen würdest, aber willst du ja nicht.

Ja aber erwartet nicht jede Programmiersprache einen Rückgabewert einer Funktion in einem bestimmten Register?
bzw. kann irgendwer hier Pascal, um mal die DLL bei Gelegenheit auszuprobieren?

btw
hat schnell irgendwer nen Link parat, wo das mit dem Wraper Zeug genauer erklärt wird?
Ich hab das gerade eben zum ersten Mal gehört, und weis nicht so recht, wonach ich suchen soll :ugly:
 
Biehler schrieb:
Ja aber erwartet nicht jede Programmiersprache einen Rückgabewert einer Funktion in einem bestimmten Register?
bzw. kann irgendwer hier Pascal, um mal die DLL bei Gelegenheit auszuprobieren?

jein wie gesagt wenn du mit inline assembler arbeitest dann ist das der fall, aber ne dll ist etwas anderes. ne dll ist so gesehen ein eigenständiges programm was vordefinierte schnittstellen für andere anwendungen beinhaltet. diese schnittstellen sind standardisiert und können somit ohnen irgendwelche umstände in anderen hochsprachen angesprochen werden...

zb in delphi sah das ungefähr so aus das du eine funktion aus einer dll so bekannt machst: (und die dll war zb mit c++ geschreiben)

function meineFuntkion(String a): String: external 'meineDLL.dll';

und dann einfach über meineFuntkion("test"); aufrufen konntest. Aber wie gesagt keine ahnung wie man ne dll in assembler zusammenbastelt.

Biehler schrieb:
hat schnell irgendwer nen Link parat, wo das mit dem Wraper Zeug genauer erklärt wird?
Ich hab das gerade eben zum ersten Mal gehört, und weis nicht so recht, wonach ich suchen soll

das ist halb so wild... nen wrapper ist nix anderes als ne zwischen schicht die als dometscher agiert. zb du hast ne funktion namens gibtMirZahl() in deiner biblotehk aber möchtest du diese jetzt in php ansprechen musst du diese entsprechend aufrufen.

das sieht so aus das man als erstes die entsprechenden php funktionen
des modules beknannt macht, (c++) mit zend_function meineExtension[] = {ZEND_FUNCTION(die_funtkion)}

und diese entsprechende implementiert:

ZEND_FUNCTION(die_funktion) {
//mach was... zb eine funktion deiner bibliotehkm aufrufen
//wie man nen dll in c++ nachläde, keine ahnung sollte aber ähnlich einfach wie mit delphi gehen
return gibtMirZahl()
}

und das wars dann eigentlich schon und in php kannste das ganze jetzt mittels die_funktion() aufrufen. (wenn du die extension geladen hast)

auf zend.com und devarticles.com gibts genügend tutorials für php extensions.

*edit* für wrapper gibts noch weitere bezeichnungen... je nachdem in wie weit man das ganze implementiert. nen wrapper war glaub ich ne komplette "übersetzung" aller funktionen, wenn du nur nen teil deiner bibliotehk implementierst war das kein wrapper mehr sondern irgendwas anders... interface? keine ahung... aber da gibts zich bezeichnungen für.
 
Zuletzt bearbeitet:
ZeroCCC schrieb:
jein wie gesagt wenn du mit inline assembler arbeitest dann ist das der fall, aber ne dll ist etwas anderes. ne dll ist so gesehen ein eigenständiges programm was vordefinierte schnittstellen für andere anwendungen beinhaltet. diese schnittstellen sind standardisiert und können somit ohnen irgendwelche umstände in anderen hochsprachen angesprochen werden...

zb in delphi sah das ungefähr so aus das du eine funktion aus einer dll so bekannt machst: (und die dll war zb mit c++ geschreiben)

function meineFuntkion(String a): String: external 'meineDLL.dll';

und dann einfach über meineFuntkion("test"); aufrufen konntest. Aber wie gesagt keine ahnung wie man ne dll in assembler zusammenbastelt.
Thx.
Dann kann ich das in Delkphgi mal ausprobieren :)
Wie man die DLL in ASM macht, weis ich schon, es existiert ja bereits eine BETA Version der DLL.


das ist halb so wild... nen wrapper ist nix anderes als ne zwischen schicht die als dometscher agiert. zb du hast ne funktion namens gibtMirZahl() in deiner biblotehk aber möchtest du diese jetzt in php ansprechen musst du diese entsprechend aufrufen.

das sieht so aus das man als erstes die entsprechenden php funktionen
des modules beknannt macht, (c++) mit zend_function meineExtension[] = {ZEND_FUNCTION(die_funtkion)}

und diese entsprechende implementiert:

ZEND_FUNCTION(die_funktion) {
//mach was... zb eine funktion deiner bibliotehkm aufrufen
//wie man nen dll in c++ nachläde, keine ahnung sollte aber ähnlich einfach wie mit delphi gehen
return gibtMirZahl()
}

und das wars dann eigentlich schon und in php kannste das ganze jetzt mittels die_funktion() aufrufen. (wenn du die extension geladen hast)

auf zend.com und devarticles.com gibts genügend tutorials für php extensions.

*edit* für wrapper gibts noch weitere bezeichnungen... je nachdem in wie weit man das ganze implementiert. nen wrapper war glaub ich ne komplette "übersetzung" aller funktionen, wenn du nur nen teil deiner bibliotehk implementierst war das kein wrapper mehr sondern irgendwas anders... interface? keine ahung... aber da gibts zich bezeichnungen für.

Ebenfalls thx.
Bei Gelegenheit werd ich mir die Seiten durchsehen.



Ich hab jetzt mal versucht, die DLL in Delphi zu verwenden:
Code:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

const
     TestLib='\masm32\test\BiehlCOMP.dll';
function AddLongDouble(var z1, z2, erg:string):string:    external TestLib;
var
  Form1: TForm1;
   z1, z2,erg:string;

implementation

{$R *.DFM}

procedure TForm1.Button1Click(Sender: TObject);
begin
    z1:='3,5';
    z2:='1,5';
    ShowMessage(AddLongDouble(z1,z2,erg));
end;

end.

Führe ich das aus, kommt ne Zugriffsverletzung.
Ich hab allerdings schon Ewigkeiten nix mehr mit Delphi gemacht :LOL:


btw
Mangels genügend C Kenntnissen:
Kann mir noch schnell jemand einen C Code geben, der auf eine Funktion in einer DLL zurückgreift, um das mal zu testen?
thx :angel:
 
Zuletzt bearbeitet:
um dir nen code zugeben bin ich leider noch net weit genug in c++

aber google doch denke mal da gibts nen code für
 
Unter Linux kannst du Shared Objects zur Laufzeit mit dlopen/dlsym/dlerror/dlclose laden.
Sieht dann etwa so aus:
man dlopen schrieb:
Code:
              #include <stdio.h>
              #include <dlfcn.h>

              int main(int argc, char **argv) {
                  void *handle;
                  double (*cosine)(double);
                  char *error;

                  handle = dlopen ("libm.so", RTLD_LAZY);
                  if (!handle) {
                      fprintf (stderr, "%s\n", dlerror());
                      exit(1);
                  }

                  dlerror();    /* Clear any existing error */
                  *(void **) (&cosine) = dlsym(handle, "cos");
                  if ((error = dlerror()) != NULL)  {
                      fprintf (stderr, "%s\n", error);
                      exit(1);
                  }

                  printf ("%f\n", (*cosine)(2.0));
                  dlclose(handle);
                  return 0;
              }
 
veers schrieb:
Unter Linux kannst du Shared Objects zur Laufzeit mit dlopen/dlsym/dlerror/dlclose laden.
Sieht dann etwa so aus:

Ah, gut zu wissen.
Danke.
Ich les mich sowieso grad in C ein, dann kann ich auch gleich ein bischen mit C unter Linux herumspielen :D

bartman schrieb:
Bevor ich hier wilden Spagetticode poste, guck dir den Link mal an:

https://sig9.com/node/35

Besonders der untere Teil mit dem dyn. Linken ist spannend.

Schön kurz und knapp

thx :kiss:
 
Hi,
ich probiere immer noch mit C und der DLL herum.
Ich will jetzt eine Funktion (AddLongInt) aufrufen.
Diese erwartet 3 Parameter: Zahl1, Zahl2 und Ergebnis.

Code:
#include <windows.h>
#include <stdio.h>	

int main () {
	char erg[1];
	char zahl3[100];
	/*Typedef the hello function*/
	typedef void (*pfunc)(char[1], char[1], char[1]);
	
	/*Windows handle*/
	HINSTANCE hdll;
	
	/*A pointer to a function*/
	pfunc hello;
	
	/*LoadLibrary*/
	hdll = LoadLibrary("/masm32/test/BiehlCOMP.dll");

	/*GetProcAddress*/

	hello = (pfunc)GetProcAddress(hdll, "AddLongInt");
	/*Call the function*/

	[b]hello("389","68",zahl3);[/b]
	FreeLibrary(hdll);

	printf("%s",zahl3);

	
	MessageBox(0,"abc","12",MB_OK);
	

	return 0;
}

Bei dick markiertem hängt es.
Rufe ich hello("123","12",zahl3) auf (also mit Zahlen unterschiedlicher Länge), schließt sich das Konsolenfenster sofort wieder.
Rufe ich hingegen hello("123","123",zahl3) auf (mit Zahlen gleicher Länge), so wird das Ergebnis ausgegeben.

Das Paradoxe: Wenn ich die FUnktion aus einem Assemblerprogramm heraus aufrufe, funktioniert sie.

Ich denke deswegen, dass ich irgendwas an dem C Code falsch gemacht hab, der ASM Code muss demzufolge eigentlich funktinieren.

Aber vorsichtshalber poste ich den auch mal:

Code:
AddLongInt PROC STDCALL Q1:DWORD, Q2:DWORD, ERG:DWORD

	PUSH ESI
	PUSH EDI
	PUSH EBX
	PUSH ECX
	
	MOV ECX, 0
	MOV EDI, Q1			;  Quelle1
	MOV ESI, Q2			;+ Quelle2
	MOV EBX, ERG		;= Ergebnis
	
						;Setze alle Variablen auf 0
	MOV TEMP, 0
	MOV Q1_LEN, 0
	MOV Q2_LEN, 0
	MOV ERG_LEN, 0
	
						;Ermittle Länge v. Zahl1
	INVOKE Len, Q1
	MOV Q1_LEN, EAX
	INVOKE Len, Q2
	MOV Q2_LEN, EAX
	
	
	;DEC Q1_LEN
	;DEC Q2_LEN
	ADD ESI, Q2_LEN
	ADD EDI, Q1_LEN
	DEC ESI
	DEC EDI


	
BCOMP_MAIN_LOOP:
	MOV AL, [ESI]
	MOV AH, [EDI]
	DEC ESI
	DEC EDI
	DEC Q1_LEN
	DEC Q2_LEN
						;Hauptteil: Berechnung und speicherung
	SUB AL, 48
	SUB AH, 48
	ADD AL, AH
	ADD AL, TEMP		;Addiere Übertrag letzter Addition
	XOR AH, AH
	PUSH EBX
	MOV BL, 10
	DIV BL
	POP EBX
	;Quotient AL
	;Rest AH
	MOV TEMP, AL		;Speichere Übertrag
	ADD AH, 48
	MOV [EBX],AH
	INC EBX
	INC ERG_LEN
						;Überprüfung, welche Zahl länger ist, und Überprüfung, ob Berechnung zu Ende ist
	MOV EAX, Q1_LEN
	CMP EAX, Q2_LEN
	JE BCOMP_LEN_EQUAL
	JA BCOMP_Q1_ABOVE
	JB BCOMP_Q2_ABOVE
	
BCOMP_Q1_ABOVE:
	CMP Q1_LEN, 0
	JE BCOMP_READY
	CMP Q2_LEN, 0
	JA BCOMP_MAIN_LOOP  ;Wenn Q2_Len =0, ist die Zahl zuende: Fülle mit Nullen aus
	MOV Q2_LEN, 1
	INC ESI
	MOV [ESI], BYTE PTR 48
	JMP BCOMP_MAIN_LOOP
	
BCOMP_Q2_ABOVE:
	CMP Q2_LEN, 0
	JE BCOMP_READY
	CMP Q1_LEN, 0
	JA BCOMP_MAIN_LOOP
	MOV Q1_LEN, 1
	INC EDI
	MOV [EDI], BYTE PTR 48
	JMP BCOMP_MAIN_LOOP
	
BCOMP_LEN_EQUAL:
	CMP Q1_LEN, 0
	JE BCOMP_READY
	CMP Q2_LEN, 0
	JE BCOMP_READY
	JMP BCOMP_MAIN_LOOP
	
BCOMP_READY:			;Ist noch ein Übertrag vorhanden?
	
	CMP TEMP, 0
	JE BCOMP_ADD_NO_TEMP
	MOV Al, TEMP
	ADD AL, 48
	MOV [EBX], AL
	INC EBX
	INC ERG_LEN
	
BCOMP_ADD_NO_TEMP:
	;Drehe nun den String um.
	;Tausche dazu das erste und das letzte BYte, usw.
	
	MOV ESI, ERG	;ESI zeigt auf den Anfang des Ergebnisses
	MOV EDI, ERG	
	ADD EDI, ERG_LEN;EBX		
	DEC EDI			;EDI zeigt auf das Ende des Ergebnis-stringes
	;DEC EDI
	
BCOMP_CH_LOOP:
	MOV AL, [ESI]
	MOV AH, [EDI]
	MOV [EDI], AL
	MOV [ESI], AH	;Letztes-x und erstes+x Byte vertauschen

	INC ESI
	DEC EDI
	CMP EDI, ESI
	JE BCOMP_ALL_OK
	JB BCOMP_ALL_OK
	JMP BCOMP_CH_LOOP
	
BCOMP_ALL_OK:
	MOV ESI, ERG
	ADD ESI, ERG_LEN
	MOV [ESI], BYTE PTR 0
	POP ECX
	POP EBX
	POP EDI
	POP ESI
	
	RET
AddLongInt ENDP
An Fehlermeldungen wird nichts ausgegeben :(

//EDIT:
OK. Habs nun selber gelöst.
Manchmal hilft nachdenken doch :ugly:
 
Zuletzt bearbeitet: