Ach die Zeilenumbrüche Das scheint beim Kopieren schief gelaufen zu sein. Ich habe mir das Eingefügte nicht nochmal angesehen. Habe es jetzt mal korrigiert.
Gruß Volkmar
Ach die Zeilenumbrüche Das scheint beim Kopieren schief gelaufen zu sein. Ich habe mir das Eingefügte nicht nochmal angesehen. Habe es jetzt mal korrigiert.
Gruß Volkmar
Zum aktuellen Stand:
Im Großen und Ganzen funktioniert mein Inline-Assembler schon.
window 1000,1000
ASM "MeineFunktion", 2
push ebp
mov ebp,esp
mov eax,par1
mov ebx,par2
add eax,ebx
mov esp,ebp
pop ebp
ENDASM
' Var Long Ergebnis = MeineFunktion(34, 87)
' Print Ergebnis
Print "Fertig!"
WaitInput
Alles anzeigen
Er schreibt zwar das Programm noch nicht in den Speicher, aber erzeugt schon mal folgende Debug-Ausgabe:
MeineFunktion - 2
0000 55 PUSH ebp
0001 89E5 MOV ebp,esp
0003 8B4508 MOV eax,par1
0006 8B5D0C MOV ebx,par2
0009 01D8 ADD eax,ebx
000B 89EC MOV esp,ebp
000D 5D POP ebp
5589E58B45088B5D0C01D889EC5D
Alles anzeigen
Das Bereitstellen des Speichers, das Schreiben der Bytes in den Speicher und das Hinzufügen der Funktion zu den importierten Funktionen ist dann wohl nur noch eine Fingerübung, die ich wegen der fortgeschrittenen Stunde auf morgen Abend verschiebe. Ach ja: Das "RET n", wobei n die Anzahl der Parameter * 4 ist, fehlt auch noch.
Gruß
Roland
Viel mehr kann ich der Dokumentatation zu FASMDLL nicht entnehmen. Nur, daß er für das HalloWelt-Demo schon mal 8 MB Speicher reserviert hat. Der Beispielcode beginnt mit dem üblichen org 100h und macht nichts weiter als per INT21 den Text auszugeben, ist für uns also ohnehin nicht zu gebrauchen.
Gruß Volkmar
Umgestrickt auf Prof-11, dank RGH läuft es nun auch da!
Dankeeeee!
CLS:Declare Zeile$,err$,DLL&,Bereich#,Start&,Zahl&:Dim Bereich#,2048
DLL&=ImportDLL("C:\\Users\\User\\AppData\\Roaming\\fasmDLL\\FASM.DLL","")
Zeile$="\
push ebp\n\
mov ebp,esp\n\
mov eax,[ebp + 8]\n\
mov ebx,[ebp + 12]\n\
add eax,ebx\n\
add eax,ebx\n\
mov esp,ebp\n\
pop ebp\n\
ret 8\z"
::::print " DLL geladen OK":beep:waitinput
err$ = fasm_Assemble(addr(Zeile$),Bereich#,SizeOf(Bereich#),100,0) ' <<<<< Klappt jetzt
Print err$
Start&=long(Bereich#,8)
Zahl& =long(Bereich#,4)
Print "\n Code:",Zahl&,"Bytes"
While Zahl&
WhileLoop 8
Print Right$("00"+Hex$(Byte(Start&,0)),2),
Inc Start&
Dec Zahl&
CaseNot Zahl&:Break
EndWhile
Print
EndWhile
Dispose Bereich#
FreeDll DLL&
WaitInput
End
Alles anzeigen
Versuche es mal mit Addr(Zeile$) als ersten Parameter. Ich weiß jetzt nicht auswendig, ab wann man das Addr() weglassen konnte.
Gruß
Roland
HURRA, das wars - Danke RGH!
Korrektur oben eingearbeitet.
Roland meinte die fehlenden Zeilenumbrüche des
XProfan-Quelltextes, wenn man diesen hier im
Forumsbeitrag in den XProfedit kopiert. Den mußte
ich auch erst trennen und neu zusammenklabustern.
Hat nichts mit der Ausgabe des Programms zu tun.
Das mit den Werten 66 und 67 kann ich auch
bestätigen.
PS: Da die DLL ja noch eine Funktion hat, die
Dateien aktzeptiert, leg doch mal die paar Zeilen
als Datei ab und laß dir den Output ausgeben.
Vielleicht kommen wir dann der Sache auf den Grund.
Jetzt muß ich aber schnell zur Arbeit.
Ich denke mal, das hat folgenden Grund:
Aus Kompatibilitätsgründen kennen 32-Bit-CPUs einen Modus um 16-Bit-Codes laufen zu lassen. (Ansonsten wäre es ja nicht möglich gewesen, auf Rechnern mit 32-Bit-CPU auch DOS oder Windows 31 laufen zu lassen.) Dafür zuständig ist der sogenannte PROECTED MODE der CPU. Andererseits ist es auch in diesem Modus möglich, die 32-Bit-Befehle zu nutzen. Dafür dienen wohl 66 bzw. 67 als Krennzeichen. Umgekehrt kann man im 32-Bit-FLAT MODE auch die 16-Bit-Varianten dieser Befehle nutzen, indem man die 66 voranstellt. (Es dürfte aber kaum Gründe geben dies zu tun.)
So wie es asussieht, assembliert der FASM für den 16-Bit-Modus. Der erzeugte Code läuft daher nicht im 32-Bit-Modus.
Gruß
Roland
Jetzt hab' ich's!
Wenn die erste Zeile USE32 ist, wird 32-Bit-Code erzeugt! Allerdings braucht der Assembler dann mehr als die mageren 1024 Byte an Speicher. Ich habe mal die in der Doku empfohlene Größe von $8000 eingestellt. Dann klappt es mit 32 Bit und das Ergebnis kann mit CALL aufgerufen werden. So funktioniert es:
Declare String Zeile, err, Handle DLL
Declare Memory Bereich
Declare Pointer Start
Declare Int Zahl
Dim Bereich, $8000
Cls
DLL = ImportDLL("D:\\RGH\\FASM\\FASM.DLL", "")
Zeile = "use32\n" + \
"push ebp\n" + \
"mov ebp, esp\n" + \
"mov eax, [ebp + 8]\n" + \
"mov ebx, [ebp + 12]\n" + \
"add eax, ebx\n" + \
"mov esp, ebp\n" + \
"pop ebp\n" + \
"ret 8\z"
err = fasm_Assemble(Zeile, Bereich, SizeOf(Bereich), 100, 0)
Print err
Start = long(Bereich, 8)
Zahl = long(Bereich, 4)
Print
Print "Code:", Zahl, "Bytes"
Print
// Aufruf des Codes
Print call(Start, 45, 78)
Print
if Zahl > 0
While Zahl
WhileLoop 8
Print Right$("00" + Hex$(Byte(Start,0)), 2),
Inc Start
Dec Zahl
CaseNot Zahl : Break
EndWhile
Print
EndWhile
EndIf
WaitInput
Dispose Bereich
FreeDll DLL
End
Alles anzeigen
Gruß
Roland
... oder in XProfan-11:
Cls
Declare Zeile$, err$, DLL%, Bereich#, Start%, Zahl&, Ver&, build&,a&,b&,c&
Dim Bereich#, $8000
DLL%=ImportDLL("C:\\Program Files (x86)\\XProfan11\\fasmDLL\\FASM.DLL","")
Ver& = fasm_GetVersion():build&=ver&>>16:Ver& = Ver& and $FFFF
font 2:print "\n Flat Assembler, DLL-Version ";ver&,"build: ";build&:font 0
Zeile$ = "\
use32 ; Erzeuge 32-bit-Code \n\
jmp weiter \n\
const1 dd 3,2,1 \n\
weiter: push ebp \n\
mov ebp, esp \n\
mov eax, [ebp + 8] \n\
mov ebx, [ebp + 12] \n\
\
add eax, ebx \n\
add eax, ebx \n\
\
mov esp, ebp \n\
pop ebp \n\
ret 8 \z"
err$ = fasm_Assemble(addr(Zeile$), Bereich#, SizeOf(Bereich#), 100, 0)
if err$<>"0":Print err$
sound 700,150:waitinput
goto "Exxxit"
endif
Start% = long(Bereich#, 8)
Zahl& = long(Bereich#, 4)
Print
Print " Code:",Zahl&,"Bytes"
Print
if Zahl&>0
While Zahl&
WhileLoop 8
Print "$";Right$("00"+Hex$(Byte(Start%,0)),2);
Inc Start%:Dec Zahl&:CaseNot Zahl&:Break
print ",";
EndWhile
Print
EndWhile
EndIf
font 2
Print "\n Testlauf:"
print "\n Asm-Funktion mit 2 Parametern dd "
print "\n Par1 = ";:input a&
print "\n Par2 = ";:input b&
print "\n Sollwert = Par1+ 2 * Par2 = ";int(a&+2*b&)
Print "\n Aufruf des OpCodes liefert: ";
// Aufruf des Codes
Print call(long(Bereich#,8), a&,b&)
sound 1600,32
WaitInput
Exxxit:
Dispose Bereich#
FreeDll DLL%
End
Alles anzeigen
Diese Fasm.dll stammt vom Sonntag, 06. Dezember 2015, 10:11:34 und trägt die Versionsnummer 1.71.49.0. Interessant wäre allerdings, auf welcher Fasm-Vollversion sie beruht. Wenn die defaultmäßig noch auf 16-bit-Code arbeitet, dürfte sie vermutlich ziemlich alt sein...
Sodele: Der Inline-Assembler von XProfan X4 funktioniert bei mir:
CLS
ASM "MeineFunktion", 2
mov eax,par1
mov ebx,par2
add eax,ebx
ENDASM
Var Long Ergebnis = MeineFunktion(38764, 879879878)
Print Ergebnis
Print "Fertig!"
WaitInput
Alles anzeigen
Das Ergebnis stimmt. Und das im Debug-Modus erzeugte Assembler-Listing sieht so aus:
MeineFunktion - 2
0000 55 PUSH ebp
0001 89E5 MOV ebp,esp
0003 8B4508 MOV eax,par1
0006 8B5D0C MOV ebx,par2
0009 01D8 ADD eax,ebx
000B 89EC MOV esp,ebp
000D 5D POP ebp
000E C20800 RET 8
5589E58B45088B5D0C01D889EC5DC20800
Alles anzeigen
Das zwingend notwendige "PUSH EBP" und "MOV EBP,ESP" am Anfang, sowie das "MOV ESP,EBP" und "POP EBP" und das "RET x" fügt XProfan selbsttätig hinzu. Vopm ESP-Register (Stack) sollte man auf alle Fälle im Code die Finger lassen!
Das Erzeugen des Assembler-Listing (Funktionsname + ".asm") werde ich über eine SET-Methode einstellbar machen.
Jetzt gilt es noch, Fehler abzufangen, den Code fehler-toleranter zu gestalten, etc. (Leerzeichen vor oder nach dem '+' bei Offsets führen derzeit noch zum Absturz.)
Kurz: Es sieht gut aus! Die Subscriptionsphase für X4 wird wohl noch im April starten.
Gruß
Roland
Und hier ein etwas komplexeres Beispiel mit Sprüngen und Strings direkt aus dem XProfan-Quellcode (Verschlüsselungsroutine, basierend auf einem Assemblercode von Frank Abbing):
window 1000,1000
declare string text, pw
ASM "crypt", 2
// Crypt proc
PUSH EBX
PUSH ESI
PUSH EDI
PUSH EBP
// setze AnsiString-Pointer
MOV EDX, Par1 // s
MOV ECX, [edx-4] // len(s)
MOV EBX, Par2 // pw
MOV ESI, [ebx-4] // len(pw)
MOV EDI,0
@@jaguar:
mov al,[edx]
xor al,[ebx+edi]
mov [edx],al
inc edx
inc edi
cmp esi,edi
jne @@kniez
mov edi,0
@@kniez:
sub ecx,1
jne @@jaguar
XOR EAX, EAX
POP EBP
POP EDI
POP ESI
POP EBX
ENDASM
text = "Mein Text"
pw = "Pass22"
Var Long Ergebnis = Crypt(text, pw)
Print Ergebnis
Print text
Crypt(text, pw)
Print text
WaitInput
Alles anzeigen
Die vier PUSH un POP am Anfnag/Ende kann man auch weglassen. Beim Delphi-Inline-Assembler sind sie empfehlenswert, da Delphi die Register auch zur Parameterübergabe nutzt. Die "@@" bei den Labels kann man auch weglassen. Ich habe den Teil eben einfach aus meinem Delphicode kopiert und lediglich "Par1" und "Par2" eingesetzt.
Gruß
Roland
PS: Da die DLL ja noch eine Funktion hat, die
Dateien aktzeptiert, leg doch mal die paar Zeilen
als Datei ab und laß dir den Output ausgeben.
Zusammen mit Rolands Tip (USE32) geht auch das. Ich hoffe, ich habe die Fehlerbehandlung einigermaßen hingekriegt. In einem Dialog kann eine *.ASM-Datei mit dem Quellcode gewählt werden. War der Vorgang erfolgreich, kann auf Nachfrage eine gleichnamige *.BIN-Datei erzeugt werden. Die enthält dann den Bytecode. Der könnte per BlockRead in einen Bereich geladen und mit CALL aufgerufen werden. Alternativ kann man den Bytecode ja auch als Ressource einbauen und von dort laden
Def %FASM_OK 0 ; FASM_STATE points to output
Def %FASM_WORKING 1
Def %FASM_ERROR 2 ; FASM_STATE contains error code
Def $FASM_Errors "OK,arbeite,Fehler,\n\
Ungültiger Parameter,\
Zu wenig Speicher,\
Stacküberlauf,\
Quelle nicht gefunden,\
Unerwartetes Codeende,\
Formatgrenzen überschritten,\
Code kann nicht erstellt werden,\
Fehler beim Schreiben"
Def $FASMERR "Datei nicht gefunden,\
Lesefehler in Quelldatei,\
Ungültiges Format in Quelldatei,\
Ungültige Macroargumente,\
Unvollständiger Macro,\
Unerwartetes Zeichen,\
Ungültiges Argument,\
Illegale Instruktion,\
Ungültiger Operand,\
Unbekannte Operandengröße,\
Fehlende Operandengröße,\
Unpassende Operandengröße,\
Ungültige Adressgröße,\
Adressgröße unpassend,\
Unzulässige Registerkombination,\
Nicht codierbar,\
Relativer Sprung außerhalb des Bereichs,\
Ungültiger Ausdruck,\
Ungültige Adresse,\
Ungültiger Wert,\
Wert außerhalb des zulässigen Bereichs,\
Symbol nicht definiert,\
Ungültige Symbolverwendung,\
Name zu lang,\
Ungültiger Name,\
Schlüsselwort als Symbol verwendet,\
Symbol bereits definiert,\
Stringende fehlt,\
Direktivenende fehlt,\
Unerwartete Instruktion,\
Unzulässige Zeichen,\
Section nicht richtig ausgerichtet,\
Einstellung bereits spezifiziert,\
Daten bereits definiert,\
Zu viele Wiederholungen,\
Symbol außerhalb des Bereichs,,,,\
Anwenderfehler,\
Kommentar fehlerhaft"
Declare String Datei, Ausgabe, err, Handle DLL
Declare Memory Bereich
Declare Pointer Start, Code
Declare Int Zahl, Bytes
Dim Bereich, 8000
Cls
DLL = ImportDLL("C:\Users\Volkmar\AppData\Roaming\\FASM.DLL", "") ' Pfad anpassen
Datei = LoadFile$("ASM-Datei öffnen", "*.ASM")
If Datei <> ""
Ausgabe = Translate$(Upper$(Datei), ".ASM", ".BIN")
err = fasm_AssembleFile(Datei, Bereich, SizeOf(Bereich), 100, 0)
Start = long(Bereich, 8)
Zahl = long(Bereich, 4)
Code = Start
Bytes = Zahl
If err = %FASM_OK
Print:Print "Code:", Zahl, "Bytes"
While Zahl
WhileLoop 8
Print Right$("00" + Hex$(Byte(Start, 0)), 2),
Inc Start
Dec Zahl
CaseNot Zahl : Break
EndWhile
Print
EndWhile
If MessageBox("Soll das Ergebnis in " + Ausgabe + " geschrieben werden?", "Codeausgabe", 36) = 6
Assign #1, Ausgabe
OpenRW #1
BlockWrite #1, Bereich, Code - Bereich, Bytes
If %IOResult
MessageBox("Ausgabedatei konnte nicht geschrieben werden.", "Fehler", 16)
Else
Print Bytes, " Bytes wurden in " + Ausgabe + " geschrieben"
EndIf
Close #1
EndIf
WaitInput
Else
Fehlermeldung err, Zahl, Start
EndIf
EndIf
Dispose Bereich
FreeDll DLL
End
Proc Fehlermeldung
Parameters Int Fehler, FehlerCode, Pointer Zeile
Declare String Meldung, Long ZNr
If Fehler < %FASM_OK
Meldung = SubStr$($FASM_Errors, Abs(Fehler) + 3, ",")
ElseIf Fehler = %FASM_ERROR
ZNr = Long(Zeile, 4)
Meldung = SubStr$($FASMERR, Abs(FehlerCode) - 100, ",") + " in Zeile " + Str$(ZNr, 0) + " in\n" + Upper$(String$(Long(Zeile, 0), 0))
Else
Meldung = SubStr$($FASM_Errors, Fehler, ",")
EndIf
Print "Code konnte nicht übersetzt werden!"
MessageBox(Meldung, "FASM-Fehler", 16)
EndProc
Alles anzeigen
Damit müssen Ungeduldige nicht auf X4 warten, um schon etwas basteln zu können
Gruß Volkmar
Zitat von Volkmar... auf Nachfrage eine gleichnamige *.BIN-Datei erzeugt werden. Die enthält dann den Bytecode. Der könnte per BlockRead in einen Bereich geladen und mit CALL aufgerufen werden.
Das gilt aber nur, wenn es einem gelingt, stets relative Sprünge und Bezüge zu verwenden. Falls die in einem Programm erzeugte Bereichsvariable nämlich auch nur um 1 Byte woanders zu liegen kommt, geht die Sache ansonsten schief. Und leider ist die Wahrscheinlickeit, daß der dann anzuspringende Bereich in einem anderen Programm genau dort erzeugt wird, wohin die Mnemonics als OpCode damals hinein-assembliert wurden, verschwindend gering.
Frage 1: Kann man bei FASM irgendwie sicherstellen, daß keine Absolutbezüge erzeugt werden? (Angeblich kann der uralte TASM das, also gab es zumindest mal diese Technik).
... oder:
Frage 2: Kann ich irgendwie sicherstellen, daß der Bereich an der immer gleichen Stelle erzeugt wird, z.B. sofort am Hauptprogramm-Anfang? (Die Memory Management Unit stellt ja beim derzeitigen Windows Speichermodell jedem Programm virtuelle Speicheradressen von 0 bis AFFF FFFF FFFF FFFF zur Verfügung, oder so ähnlich oder dergleichen oder was, in Wirklichkeit keine Ahnung ...)
Gruss ?!?!?!
Da hast Du natürlich Recht, es gibt Einschränkungen. Die Adresse, an der der Code dann zu liegen kommt, kann man nicht beeinflussen. Und ansonsten gilt, nur "kleine Sprünge" machen. Aber solche "Kleinigkeiten", wie Roland in #132 vorgestellt hat, kann man durchaus machen. Für größere Sachen warten wir einfach ab, was Roland uns in X4 bietet. Oder ein Assemblerfuchs verrät uns ein paar "Verbiegungen". Oder Du nutzt eben Franks XPIA. Oder...?
Wir wollten ja nur mal FASM unter Profan zum Laufen bringen.
Gruß Volkmar
Zugegeben, mein voriger Beitrag war ein bisschen gemein - sorry for that! RGH gehört für seine Leistungen insgesamt und insbesondere dafür, dass er uns gerade eine erste Alpha-Version des künftigen XProfan-X4 mit Inline-Assembler zugänglich gemacht, selbstverständlich gefeiert und sehr bedankt. Bitte vor den Vorhang!
Und um diesen Thread nicht vollends zu kapern, geht es hier weiter:
XProfan X4 mit Inlineassembler und mehr
Dort gibt es auch den erwähnten Download!
Gruß
Roland
... und jetzt schaue ich etwas NHL-Eishockey!
Abt. Komplexe Funktionen für Komplexe Zahlen
==============================
Nachstehend eine in Profan-11 zum Laufen gebrachte Studie, wie man Komplexe Zahlen als Vier-Tupel darstellen kann und dadurch manche Funktionen (z.B. trigonometrische) leicht auf Komplexe Zahlen erweitern könnte (2 Teile, bitte zusammensetzen).
Gruss
Teil 1:
WindowTitle "PGM TComplex: Operationen mit Komplexen Zahlen (Re+j*Im)"
' Q:http://jean-pierre.moreau.pagesperso-orange.fr/Basic/tcomplex_bas.txt
' (D) Demo für eine Übertragung nach XProfan-11.2a. Ohne jede Gewähr!
' 2017-03 by P.Specht, Vienna/Austria. Mögliche Rechte Dritter ungeprüft.
'
' A complex number Z is represented as an array with 4 locations:
' z(1), z(2) for algebraic form x+%j y = (x,y)
' z(3), z(4) for polar form r*exp(%i*t) = r versor t = (r \ t)
WindowStyle 24
Window %maxx*0.2,%maxy*0.1 - %maxx*0.6,%maxy*0.6
font 2
Declare ZZ![4],Z![4],Z1![4],Z2![4],temp![4],u![4] 'Complex numbers
Declare tmp!,x!,y!,r!,t!,i&
var XINF!=1.2E16 'big number
var TINY!=val("1E-16")'small
var PI!=4*ArcTan(1)
var F$="#0.0000"
x!=1 : y!=-2 : AssignXY(ZZ![],x!,y!):Z1![]=ZZ![&index]
x!=2.5: y!=5.75 : AssignXY(ZZ![],x!,y!):Z2![]=ZZ![&index]
AddCpx(ZZ![],Z1![],Z2![]):Z![]=ZZ![&index]
PRINT "\n Z1 = ";:ZZ![]=Z1![&index]:DsplCpx(ZZ![])
PRINT "\n Z2 = ";:ZZ![]=Z2![&index]:DsplCpx(ZZ![])
PRINT "\n Z1+Z2 = ";:ZZ![]=Z![&index]:DsplCpx(ZZ![])
PRINT "\n\n Z1+Z2 polar = ";:DsplCpxR(ZZ![])
PRINT "\n Z1 polar = ";:ZZ![]=Z1![&index]:DsplCpxR(ZZ![])
PRINT "\n Z2 polar = ";:ZZ![]=Z2![&index]:DsplCpxR(ZZ![])
MulCpx(ZZ![],Z1![],Z2![])
PRINT "\n\n Z1*Z2 = ";:DsplCpx(ZZ![])
PRINT "\n Z1*Z2 polar = ";:DsplCpxR(ZZ![])
DivCpx(ZZ![],Z1![],Z2![])
PRINT "\n\n Z1 / Z2 polar = ";:DsplCpxR(ZZ![])
ExpCpx(ZZ![],Z1![])
PRINT "\n\n Exp(Z1) = ";:DsplCpx(ZZ![])
PRINT "\n Exp(Z1) polar = ";:DsplCpxR(ZZ![])
x!=2.5:y!=5.75 :AssignXY(ZZ![],x!,y!)
Z1![]=ZZ![&index]
AreaSinHypCpx(ZZ![],Z1![])
PRINT "\n\n AreaSinHypCpx(Z2) = ";:DsplCpx(ZZ![])
x!=1 : y!=-2 : AssignXY(ZZ![],x!,y!):Z1![]=ZZ![&index]
x!=2.5: y!=5.75 : AssignXY(ZZ![],x!,y!):Z2![]=ZZ![&index]
SubtrCpx
PRINT "\n\n SubtrCpx(zz=z1-z2) = ";:DsplCpx(ZZ![])
ChgSgnCpx
PRINT "\n ChgSgnCpx(zz) = ";:DsplCpx(ZZ![])
ConjugCpx
PRINT "\n ConjugCpx(zz) = ";:DsplCpx(ZZ![])
LnCpx
PRINT "\n LnCpx(zz) = ";:DsplCpx(ZZ![])
ExpCpx
PRINT "\n ExpCpx(zz) = ";:DsplCpx(ZZ![])
x!=1 : y!=2 :AssignXY(ZZ![],x!,y!):Z1![]=ZZ![&index]
x!=0 : y!=1 :AssignXY(ZZ![],x!,y!):Z2![]=ZZ![&index]
PowerCpx
PRINT "\n PowerCpx(zz=z1^z2) = ";:DsplCpx(ZZ![])
waitinput
cls
x!=1 : y!=2 :AssignXY(ZZ![],x!,y!):Z1![]=ZZ![&index]
CosCpx(zz![],Z1![])
PRINT "\n\n CosCpx(zz=cos Z1) = ";:DsplCpx(ZZ![])
x!=1 : y!=2 :AssignXY(ZZ![],x!,y!):Z1![]=ZZ![&index]
SinCpx(zz![],Z1![])
PRINT "\n SinCpx(zz=sin Z1) = ";:DsplCpx(ZZ![])
x!=1 : y!=2 :AssignXY(ZZ![],x!,y!):Z1![]=ZZ![&index]
TanCpx(zz![],Z1![])
PRINT "\n TanCpx(zz=tan Z1) = ";:DsplCpx(ZZ![])
x!=1 : y!=2 :AssignXY(ZZ![],x!,y!):Z1![]=ZZ![&index]
ArcCosCpx
PRINT "\n\n ArcCosCpx (zz=acos Z1) = ";:DsplCpx(ZZ![])
x!=1 : y!=2 :AssignXY(ZZ![],x!,y!):Z1![]=ZZ![&index]
ArcSinCpx(zz![],Z1![])
PRINT "\n ArcSinCpx(zz=asin Z1) = ";:DsplCpx(ZZ![])
x!=1 : y!=2 :AssignXY(ZZ![],x!,y!):Z1![]=ZZ![&index]
ArcTanCpx(zz![],Z1![])
PRINT "\n ArcTanCpx(zz=atan Z1) = ";:DsplCpx(ZZ![])
x!=1 : y!=2 :AssignXY(ZZ![],x!,y!):Z1![]=ZZ![&index]
CoshypCpx
PRINT "\n\n\n CoshypCpx(zz=cosh z1) = ";:DsplCpx(ZZ![])
x!=1 : y!=2 :AssignXY(ZZ![],x!,y!):Z1![]=ZZ![&index]
SinhypCpx
PRINT "\n SinhypCpx(zz=sinh z1) = ";:DsplCpx(ZZ![])
x!=1 : y!=2 :AssignXY(ZZ![],x!,y!):Z1![]=ZZ![&index]
TanhypCpx
PRINT "\n TanhypCpx(zz=sinh z1) = ";:DsplCpx(ZZ![])
x!=1 : y!=2 :AssignXY(ZZ![],x!,y!):Z1![]=ZZ![&index]
AreaCoshypCpx
PRINT "\n\n AreaCoshypCpx(zz=acosh z1) = ";:DsplCpx(ZZ![])
x!=1 : y!=2 :AssignXY(ZZ![],x!,y!):Z1![]=ZZ![&index]
AreaSinhypCpx
PRINT "\n AreaSinhypCpx(zz=asinh z1) = ";:DsplCpx(ZZ![])
x!=1 : y!=2 :AssignXY(ZZ![],x!,y!):Z1![]=ZZ![&index]
AreaTanhypCpx
PRINT "\n AreaTanhypCpx(zz=atanh z1) = ";:DsplCpx(ZZ![])
PRINT:beep:Waitinput
END
Proc AssignXY 'def Complex ZZ by values x (=Re) and y (=Im)
ZZ![1]=x!:ZZ![2]=y!
ZZ![3]=SQRT(sqr(x!)+sqr(y!))
IF x!=0
IF y! > 0
ZZ![4]=PI! / 2
ELSEIF y!=0
ZZ![4]=-PI! / 2
ELSE
ZZ![4]=0
ENDIF
ELSE
ZZ![4]=ArcTan(y!/x!)
IF x! < 0
IF y! >= 0
ZZ![4]=ZZ![4] + PI!
ELSE
ZZ![4]=ZZ![4] - PI!
ENDIF
ENDIF
case ZZ![4] > PI!:ZZ![4]=ZZ![4] - 2 * PI!
case ZZ![4] < (-PI!):ZZ![4]=ZZ![4] + 2 * PI!
ENDIF
EndProc
Proc AssignRT 'define Cpx number by r and t in radians
ZZ![3]=r!:ZZ![4]=t!
case ZZ![4] > PI!:ZZ![4]=ZZ![4] - 2 * PI!
case ZZ![4]<(-PI!):ZZ![4]= ZZ![4] + 2 * PI!
ZZ![1]=r! * COS(t!):ZZ![2]=r! * SIN(t!)
endproc
Proc DsplCpx 'Dspl Cpx number with x and y
PRINT "("+format$(F$,ZZ![1])+" +j* "+format$(F$,ZZ![2])+")";
Endproc
Proc DsplCpxR 'Dspl Cpx number with radius and phase in radians
PRINT "("+format$(F$,ZZ![3])+" \ "+format$(F$,ZZ![4])+")";
Endproc
Proc AddCpx 'add two Cpx numbers:ZZ=Z1+Z2
ZZ![1]=Z1![1] + Z2![1]:ZZ![2]=Z1![2] + Z2![2]
x!=ZZ![1]:y!=ZZ![2]
AssignXY(ZZ![],x!,y!)
EndProc
Proc SubtrCpx 'subtract two Cpx numbers:ZZ=Z1-Z2
ZZ![1]=Z1![1] - Z2![1]:ZZ![2]=Z1![2] - Z2![2]
x!=ZZ![1]:y!=ZZ![2]:AssignXY(ZZ![],x!,y!)
EndProc
Proc ChgSgnCpx 'change sign of a Cpx number:ZZ=-ZZ
ZZ![1]=-1*ZZ![1]:ZZ![2]=-1*ZZ![2]
x!=ZZ![1]:y!=ZZ![2]:AssignXY(ZZ![],x!,y!)
EndProc
Proc ConjugCpx 'change sign of Im of a Cpx number
ZZ![2]=-1*ZZ![2]
x!=ZZ![1]:y!=ZZ![2]:AssignXY(ZZ![],x!,y!)
EndProc
proc MulCpx 'multiply two Cpx numbers:ZZ=Z1*Z2
ZZ![3]=Z1![3] * Z2![3]:ZZ![4]=Z1![4] + Z2![4]
r!=ZZ![3]:t!=ZZ![4]
AssignRT(ZZ![],r!,t!)
endproc
Proc DivCpx 'divide two Cpx numbers:ZZ=Z1/Z2
IF Z2![3] < TINY!
ZZ![3]=XINF!
ELSE
ZZ![3]=Z1![3] / Z2![3]
ENDIF
ZZ![4]=Z1![4] - Z2![4]
r!=ZZ![3]:t!=ZZ![4]
AssignRT(ZZ![],r!,t!)
endproc
Proc ExpCpx 'exponential Cpx function:ZZ=Exp(Z1)
IF EXP(Z1![1]) > XINF!
tmp!=XINF!
ELSE
tmp!=EXP(Z1![1])
ENDIF
ZZ![1]=tmp! * COS(Z1![2]):ZZ![2]=tmp! * SIN(Z1![2])
x!=ZZ![1]:y!=ZZ![2]
AssignXY(ZZ![],x!,y!)
EndProc
Proc LnCpx 'ZZ=LN(Z1)
IF Z1![3] <= 0
ZZ![1]=-1*XINF!
ELSE
ZZ![1]=LN(Z1![3])
ENDIF
ZZ![2]=Z1![4]
x!=ZZ![1]:y!=ZZ![2]
AssignXY(ZZ![],x!,y!)
EndProc
Proc PowerCpx 'Cpx power ZZ=Z1^Z2
LnCpx(temp![],Z1![])
Whileloop 4:i&=&Loop
Z1![i&]=Z2![i&]
Z2![i&]=ZZ![i&]
endwhile
MulCpx(temp![],Z1![],temp![])
Z1![]=ZZ![&index]
ExpCpx(ZZ![],Z1![])
EndProc
Alles anzeigen
Teil 2 von 2:
Proc CosCpx 'ZZ=COS(Z1)
ZZ![1]=(EXP(-1*Z1![2]) * COS(Z1![1]) + EXP(Z1![2]) * COS(-Z1![1])) / 2
ZZ![2]=(EXP(-1*Z1![2]) * SIN(Z1![1]) + EXP(Z1![2]) * SIN(-1*Z1![1])) / 2
x!=ZZ![1]:y!=ZZ![2]
AssignXY(ZZ![],x!,y!)
EndProc
Proc SinCpx 'ZZ=SIN(Z1)
ZZ![1]=(EXP(-Z1![2]) * SIN(Z1![1]) - EXP(Z1![2]) * SIN(-1*Z![1])) / 2
ZZ![2]=-1*(EXP(-Z1![2]) * COS(Z1![1]) - EXP(Z1![2]) * COS(-1*Z![1])) / 2
x!=ZZ![1]:y!=ZZ![2]
AssignXY(ZZ![],x!,y!)
EndProc
Proc TanCpx 'ZZ=TAN(Z1)
SinCpx(ZZ![],Z1![])
temp![]=ZZ![&index]
CosCpx(ZZ![],Z1![])
whileloop 4:i&=&Loop
Z1![i&]=temp![i&]
Z2![i&]=ZZ![i&]
endwhile
DivCpx(ZZ![],Z1![],Z2![])
EndProc
Proc CoshypCpx 'ZZ=CH(Z1)
ZZ![1]=(EXP(Z1![1]) * COS(Z1![2]) + EXP(-1*Z1![1]) * COS(-1*Z1![2])) / 2
ZZ![2]=(EXP(Z1![1]) * SIN(Z1![2]) + EXP(-1*Z1![1]) * SIN(-1*Z1![2])) / 2
x!=ZZ![1]:y!=ZZ![2]
AssignXY(ZZ![],x!,y!)
EndProc
Proc SinhypCpx 'ZZ=SH(Z1)
ZZ![1]=(EXP(Z1![1]) * COS(Z1![2]) - EXP(-1*Z1![1]) * COS(-1*Z1![2])) / 2
ZZ![2]=-1*(EXP(Z1![1]) * SIN(Z1![2]) - EXP(-1*Z1![1]) * SIN(-1*Z1![2])) / 2
x!=ZZ![1]:y!=ZZ![2]
AssignXY(ZZ![],x!,y!)
EndProc
Proc TanhypCpx 'ZZ=TH(Z1)
SinhypCpx(ZZ![],Z1![])
temp![]=ZZ![&index]
CoshypCpx(ZZ![],Z1![])
whileloop 4:i&=&Loop
Z1![i&]=temp![i&]
Z2![i&]=ZZ![i&]
Endwhile
DivCpx(ZZ![],Z1![],Z2![])
EndProc
Proc ArcCosCpx 'ZZ=ARCCOS(Z1)
Z![]=Z1![&index]
temp![1]=1 - sqr(Z1![1]) + sqr(Z1![2])
temp![2]=-2 * Z1![1] * Z1![2]
x!=temp![1]:y!=temp![2]:AssignXY(ZZ![],x!,y!)
Z1![]=ZZ![&index]
x!=0.5:y!=0:AssignXY(ZZ![],x!,y!)
Z2![]=ZZ![&index]
PowerCpx(ZZ![],Z1![],Z2![])
tmp!=ZZ![1]
ZZ![1]=Z![1] - ZZ![2]
ZZ![2]=Z![2] + tmp!
x!=ZZ![1]:y!=ZZ![2]
AssignXY(ZZ![],x!,y!)
Z1![]=ZZ![&index]
LnCpx(ZZ![],Z1![])
tmp!=ZZ![1]
ZZ![1]=ZZ![2]:ZZ![2]=-1*tmp!
x!=ZZ![1]:y!=ZZ![2]
AssignXY(ZZ![],x!,y!)
EndProc
Proc ArcSinCpx 'ZZ=ARCSIN(Z1)
Z![]=Z1![&index]
temp![1]=1 - sqr(Z1![1]) + sqr(Z1![2])
temp![2]=-2 * Z1![1] * Z1![2]
x!=temp![1]:y!=temp![2]
AssignXY(ZZ![],x!,y!)
Z1![]=ZZ![&index]
x!=0.5:y!=0
AssignXY(ZZ![],x!,y!)
Z2![]=ZZ![&index]
PowerCpx(ZZ![],Z1![],Z2![])
ZZ![1]=ZZ![1] - Z![2]
ZZ![2]=ZZ![2] + Z![1]
x!=ZZ![1]:y!=ZZ![2]
AssignXY(ZZ![],x!,y!)
Z1![]=ZZ![&index]
LnCpx(ZZ![],Z1![])
tmp!=ZZ![1]
ZZ![1]=ZZ![2]:ZZ![2]=-1*tmp!
x!=ZZ![1]:y!=ZZ![2]
AssignXY(ZZ![],x!,y!)
EndProc
proc ArctanCpx 'ZZ=ARCTAN(Z1)
temp![1]=-Z1![1]:temp![2]=1 - Z1![2]
u![1]=Z1![1]:u![2]=1 + Z1![2]
x!=temp![1]:y!=temp![2]
AssignXY(ZZ![],x!,y!)
Z1![]=ZZ![&index]
x!=u![1]:y!=u![2]
AssignXY(ZZ![],x!,y!)
Z2![]=ZZ![&index]
DivCpx(ZZ![],Z1![],Z2![])
Z1![]=ZZ![&index]
LnCpx(ZZ![],Z1![])
tmp!=ZZ![1]
ZZ![1]=ZZ![2] / 2:ZZ![2]=-1*tmp! / 2
x!=ZZ![1]:y!=ZZ![2]
AssignXY(ZZ![],x!,y!)
EndProc
Proc AreacoshypCpx 'ZZ=ARGCH(Z1)
Z![]=Z1![&index]
temp![1]=-1 + sqr(Z1![1]) + sqr(Z1![2])
temp![2]=2 * Z1![1] * Z1![2]
x!=temp![1]:y!=temp![2]
AssignXY(ZZ![],x!,y!)
Z1![]=ZZ![&index]
x!=0.5:y!=0
AssignXY(ZZ![],x!,y!)
Z2![]=ZZ![&index]
PowerCpx(ZZ![],Z1![],Z2![])
ZZ![1]=ZZ![1] + Z![1]
ZZ![2]=ZZ![2] + Z![2]
x!=ZZ![1]:y!=ZZ![2]
AssignXY(ZZ![],x!,y!)
Z1![]=ZZ![&index]
LnCpx(ZZ![],Z1![])
EndProc
proc AreaSinHypCpx
Z![]=Z1![&index]
temp![1]=1 + sqr(Z1![1]) - sqr(Z1![2])
temp![2]=2 * Z1![1] * Z1![2]
x!=temp![1]:y!=temp![2]
AssignXY(ZZ![],x!,y!)
Z1![]=ZZ![&index]
x!=0.5:y!=0:AssignXY(ZZ![],x!,y!)
Z2![]=ZZ![&index]
PowerCpx(ZZ![],Z1![],Z2![])
x!=ZZ![1] + Z![1]:y!=ZZ![2] + Z![2]
AssignXY(ZZ![],x!,y!)
Z1![]=ZZ![&index]
LnCpx(ZZ![],Z1![])
Endproc
Proc AreatanhypCpx 'ZZ=ARGTH(Z1)
Z![]=Z1![&index]
Z1![1]=1 + Z![1]:Z1![2]=Z![2]
Z2![1]=1 - Z![1]:Z2![2]=-1*Z![2]
x!=Z1![1]:y!=Z1![2]
AssignXY(ZZ![],x!,y!)
Z1![]=ZZ![&index]
x!=Z2![1]:y!=Z2![2]
AssignXY(ZZ![],x!,y!)
Z2![]=ZZ![&index]
DivCpx(ZZ![],Z1![],Z2![])
Z1![]=ZZ![&index]
LnCpx(ZZ![],Z1![])
ZZ![1]=ZZ![1]/2:ZZ![2]=ZZ![2]/2
x!=ZZ![1]:y!=ZZ![2]
AssignXY(ZZ![],x!,y!)
EndProc
Alles anzeigen
Sie haben noch kein Benutzerkonto auf unserer Seite? Registrieren Sie sich kostenlos und nehmen Sie an unserer Community teil!