frage bezüglich ASM

Für allgemeine Fragen zur Programmierung mit PureBasic.
Kevin
Beiträge: 236
Registriert: 11.06.2007 12:55

frage bezüglich ASM

Beitrag von Kevin »

Hi,

ich brauche eure Hilfe bezüglich dieses codes

wie bekomme ich das zum laufe ohne die Variable "a" als Global zu deklarieren?

Code: Alles auswählen

;Global a

Procedure Test_()
  a = 1
  
  !JMP l_start
  
  func:;{
  a = 2
  !RET;}
    
  start:
    
  !CALL l_func
  
  Debug a
  
EndProcedure

Test_()
ich vermute es liegt am CALL da ich gelesen hab das man es nicht innerhalb von Proceduren verwenden sollte...

Ich bedanke mich schon mal im Voraus
Kevin
Beiträge: 236
Registriert: 11.06.2007 12:55

Re: frage bezüglich ASM

Beitrag von Kevin »

so funktioniert es ich weiß aber nicht ob das richtig ist.

Code: Alles auswählen

;Global a

Procedure Test_()
  var = 1
  temp=0
  
  !JMP l_start
  
  func:;{
  !pop edx; adresse popen und in v_temp zwischenspeichern
  !mov [p.v_temp],edx
  
  var = 2
  Debug var
  
  
  !mov edx,[p.v_temp]
  !push edx; adresse wieder pushen
  !RET;}
  
  
  start:
  
  !CALL l_func
  
  
  Debug "d2: "+Str(var)
  
  
EndProcedure

Test_()
vielleicht weiß ja noch einer eine bessere Lösung.
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Re: frage bezüglich ASM

Beitrag von ts-soft »

Warum überhaupt das ASM Gefrickel? Geschwindigkeitsgewinn gegenüber Gosub : Return dürfte nicht messbar
sein. Selbst die Verwendung von Proceduren kosten lediglich einen Call und dürften von der Geschwindigkeit nicht
viel ändern.

Ich nehme mal an, das ist für Deinen Interpreter, der dadurch IMHO nicht schneller wird.

Gruß
Thomas
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7039
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: frage bezüglich ASM

Beitrag von STARGÅTE »

Gosub arbeitet leider nicht mit Dynamischen Adressen.
Obwohl Gosub:Return exakt den ASM-Code hat, wie eine Procedure, nur halt ohne Parameter.

Aber ich muss TS-Soft Recht geben, du (Kevin) machst dir vermutlich zu viel Arbeit, um im Endeffekt ein nicht viel schnelleren Code zu erzeugen als mit Prozeduren.

Ich habe zumindest (obwohl ich ja auch die Vorteile sah) inzwischen den Idee verworfen, und nutze weiter meine Prozeduren-Bäume.
Vorallem deswgeen, weil ich mich zu wenig mit ASM auskenne, und dadurch angst habe.
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Kevin
Beiträge: 236
Registriert: 11.06.2007 12:55

Re: frage bezüglich ASM

Beitrag von Kevin »

@ts-Soft, STARGÅTE

Hier erst noch ein Code der die Geschwindigkeitsvorteile zeigen soll:

Code: Alles auswählen

#DL=10000000

Procedure _49(*long.long)
  *long\l+1*2
EndProcedure

Prototype.i Beispiel(a.i)

Structure ProzedurListe
  Beispiel.Beispiel[50]
EndStructure

Define ProzedurListe.ProzedurListe
ProzedurListe\Beispiel[49] = @_49()


a.l = 0
time = ElapsedMilliseconds()
For z=1 To #DL
  
  test= 49
  
  ProzedurListe\Beispiel[test](@a)
  
  
Next
time = ElapsedMilliseconds() - time

MessageRequester(Str(a),"proceduren: "+StrD(time/1000,3)+"sec")






a = 0
time = ElapsedMilliseconds()
For z=1 To #DL
  
  test= 49
  
  Select test
    Case 1:Case 2:Case 3
    Case 4:Case 5:Case 6
    Case 7:Case 8:Case 9
    Case 10:Case 11:Case 12
    Case 13:Case 14:Case 15
    Case 16:Case 17:Case 18
    Case 19:Case 20:Case 21
    Case 22:Case 23:Case 24
    Case 25:Case 26:Case 27
    Case 28:Case 29:Case 30
    Case 31:Case 32:Case 33
    Case 34:Case 35:Case 36
    Case 37:Case 38:Case 39
    Case 40:Case 41:Case 42
    Case 43:Case 44:Case 45
    Case 46:Case 47:Case 48
    Case 49
      a+1*2
  EndSelect
Next

time = ElapsedMilliseconds() - time

MessageRequester(Str(a),"select/case "+StrD(time/1000,3)+"sec" )




Debug ohne Debugger starten!



Goto ende

_01:;Case 01
_02:;Case 02
_03:;Case 03
;.........
_48:;Case 48
_49:;Case 49
a+1*2
!RET
ende:


Structure labellist
  labels.i[50]
EndStructure
Global labellist.labellist
labellist\labels[49] = ?_49
Global TARGET

a = 0
time = ElapsedMilliseconds()
For z=1 To #DL
  
  test= 49
  
  TARGET = labellist\labels[test]
  !CALL [v_TARGET]
  
Next
time = ElapsedMilliseconds() - time

MessageRequester(Str(a),"CALL variante: "+StrD(time/1000,3)+"sec")
ich könnte natürlich auch proceduren verwenden aber dann müsste ich die benötigten Variablen als Parameter übergeben was langsamer ist als CALL da ich damit die variablen weiterhin direkt ansprechen kann.
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Re: frage bezüglich ASM

Beitrag von ts-soft »

30 ms bei 10 Millionen aufrufen (schleife mitgemessen), wo ist da jetzt der Unterschied? :lol:

Ich sag da jetzt nichts mehr zu, tune mal weiter.
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7039
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: frage bezüglich ASM

Beitrag von STARGÅTE »

Also das Select:Case langsammer ist ist klar.

Das ein Call ohne Parameter und Rückgabe wert schneller ist, ist auch klar.

Die Frage die sich mir stellt ist:
Wie verwaltest du bzw. wie erzeugst nun dann deine Byte-Sequenz, in der dann die Jumps aufgerufen werden.

Du musst ja irgendwie auch die Operationen alle einzeln haben.
Das heißt, um A+B zu rechnen, musst du ja A und B setzen und dann auch das Ergebnis wieder irgenwie zurück geben.
Genau das macht ja n Prozedure dnan auch.

In deinem Fall benutzt du ja dieses "a". Was machst du aber nun wenn du "tiefere" Rechnungen hast. Beispiel:
(A+B)*(C+D)

Hier musst du ja irgendwie A+B und C+D "sichern" um dann zu multiplizieren.
Hier gehts halt nicht, das du immer zum ergebnis etwas dazu addierst/multiplizierst usw.

Bis jetzt ist deine Variante schneller, aber ich vermute, das du schnell noch sachen dazu schreiben musst, und du dann an die Geschwindigkeit von Prozeduren rankommst.
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Kevin
Beiträge: 236
Registriert: 11.06.2007 12:55

Re: frage bezüglich ASM

Beitrag von Kevin »

@ts-soft
mein ziel ist es halt einen schnellen Interpreter zu schreiben und dafür nehme ich das in kauf es sind ja immerhin 20-30% im Beispiel.
STARGÅTE hat geschrieben:Also das Select:Case langsammer ist ist klar.

Das ein Call ohne Parameter und Rückgabe wert schneller ist, ist auch klar.

Die Frage die sich mir stellt ist:
Wie verwaltest du bzw. wie erzeugst nun dann deine Byte-Sequenz, in der dann die Jumps aufgerufen werden.

Du musst ja irgendwie auch die Operationen alle einzeln haben.
Das heißt, um A+B zu rechnen, musst du ja A und B setzen und dann auch das Ergebnis wieder irgenwie zurück geben.
Genau das macht ja n Prozedure dnan auch.

In deinem Fall benutzt du ja dieses "a". Was machst du aber nun wenn du "tiefere" Rechnungen hast. Beispiel:
(A+B)*(C+D)

Hier musst du ja irgendwie A+B und C+D "sichern" um dann zu multiplizieren.
Hier gehts halt nicht, das du immer zum ergebnis etwas dazu addierst/multiplizierst usw.

Bis jetzt ist deine Variante schneller, aber ich vermute, das du schnell noch sachen dazu schreiben musst, und du dann an die Geschwindigkeit von Prozeduren rankommst.
Ok dann versuche ich mal zu erklären wie mein Interpreter arbeitet.

nehmen wir als Beispielcode "debug (A+B)*(C+D)"
mein Compiler würde das erst so umwandeln:

Code: Alles auswählen

tempvariable2=C+D
tempvariable1=A+B
tempvariable1*tempvariable2
debug tempvariable1
End
später beim ausführen steht es dann so im speicher:

Word [65]
Integer [pointer zu variable/wert 1]
Integer [pointer zu variable/wert 2]
Integer [pointer zu variable/wert 3]
;65 ist der bytecode für (=+) einer variable erst einen wert zuweisen und anschließend noch einen wert addieren was "tempvariable2=C+D" enspricht

Word [65]
Integer [pointer zu variable/wert 1]
Integer [pointer zu variable/wert 2]
Integer [pointer zu variable/wert 3]
; > tempvariable1=A+B

Word [14]
Integer [pointer zu variable/wert 1]
Integer [pointer zu variable/wert 2]
; 14: einen wert mit einem anderen multiplizieren > tempvariable1*tempvariable2

Word [40]
Integer [pointer zu variable/wert 1]
; 40 ist Debug einen wert ausgeben -> debug tempvariable1

Word [5]
; 5 ist End

mein Interpreter arbeitet es dann nacheinander ab.
ungefähr so:

Code: Alles auswählen

repeat
code=Peekw(*position) :*position+2

select code
case 5
break
case 14; *
pointer1=peeki(*position):*position+sizeof(intger)
pointer2=peeki(*position):*position+sizeof(intger)
poke(pointer1,peek(pointer1)*peek(pointer2))

case 40; debug
wert=peek(*position):*position+sizeof(intger)
debug wert

case 65
pointer1=peeki(*position):*position+sizeof(intger)
pointer2=peeki(*position):*position+sizeof(intger)
pointer3=peeki(*position):*position+sizeof(intger)
poke(pointer1,peek(pointer2)+peek(pointer3))
default
break
endselect;(select/case hab ich ja jetzt durch JMP/CALL ersetzt. Ist hier nur zum einfacheren Verständnis)

forever
Das ist jetzt natürlich extrem zusammengefasst da ja auch noch überall der Variablentyp beachtet werden muss usw...
Ich hoffe das hat dir geholfen zu verstehen wie mein Programm arbeitet.
Und noch als Hinweis mein Programm ist schon "fertig" ich möchte es jetzt nur noch so schnell wie möglich machen.

__________________________________________________
Code-Tags hinzugefügt
03.07.2011
RSBasic
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7039
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: frage bezüglich ASM

Beitrag von STARGÅTE »

Hm und genau sowas:

Code: Alles auswählen

pointer1=peeki(*position):*position+sizeof(intger)
pointer2=peeki(*position):*position+sizeof(intger)
pointer3=peeki(*position):*position+sizeof(intger)
poke(pointer1,peek(pointer2)+peek(pointer3))
erscheint mir sehr langsam, weil du selbst immer noch Zwischenschritte hast.
Dann optimiere an dieser Stelle noch so (explizit für dieses Beispiel):
Erstelle für jede Operation (in deinem Fall C = A + B) eine Struktur:

Code: Alles auswählen

Structure SetAndAdd
	*Result.Integer
	*Value1.Integer
	*Value2.Integer
EndStructure
Dann kannst du deine umständliche Peek/Poke sache in eine elegante schnelle Zeile schreiben:

Code: Alles auswählen

*Position.SetAndAdd
*Position\Result\i = *Position\Value1\i + *Position\Value2\i
*Position + SizeOf(SetAndAdd)
Hier n Demo:

Code: Alles auswählen

Structure SetAndAdd
   *Result.Integer
   *Value1.Integer
   *Value2.Integer
EndStructure

A.i = 123
B.i = 456
C.i

*Position.SetAndAdd = AllocateMemory(SizeOf(SetAndAdd))
*Position\Result = @C
*Position\Value1 = @A
*Position\Value2 = @B

*Position\Result\i = *Position\Value1\i + *Position\Value2\i

Debug C
Das sollte dein Script um einiges beschleunigen.

EDIT: In diesem Fall von 47 Taktzyklen bei Peek/Poke auf 15 Taktzyklen mit der Strukturvariante
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Kevin
Beiträge: 236
Registriert: 11.06.2007 12:55

Re: frage bezüglich ASM

Beitrag von Kevin »

STARGÅTE hat geschrieben:Hm und genau sowas:

Code: Alles auswählen

pointer1=peeki(*position):*position+sizeof(intger)
pointer2=peeki(*position):*position+sizeof(intger)
pointer3=peeki(*position):*position+sizeof(intger)
poke(pointer1,peek(pointer2)+peek(pointer3))
erscheint mir sehr langsam, weil du selbst immer noch Zwischenschritte hast.
Dann optimiere an dieser Stelle noch so (explizit für dieses Beispiel):
Erstelle für jede Operation (in deinem Fall C = A + B) eine Struktur:

Code: Alles auswählen

Structure SetAndAdd
	*Result.Integer
	*Value1.Integer
	*Value2.Integer
EndStructure
Dann kannst du deine umständliche Peek/Poke sache in eine elegante schnelle Zeile schreiben:

Code: Alles auswählen

*Position.SetAndAdd
*Position\Result\i = *Position\Value1\i + *Position\Value2\i
*Position + SizeOf(SetAndAdd)
Hier n Demo:

Code: Alles auswählen

Structure SetAndAdd
   *Result.Integer
   *Value1.Integer
   *Value2.Integer
EndStructure

A.i = 123
B.i = 456
C.i

*Position.SetAndAdd = AllocateMemory(SizeOf(SetAndAdd))
*Position\Result = @C
*Position\Value1 = @A
*Position\Value2 = @B

*Position\Result\i = *Position\Value1\i + *Position\Value2\i

Debug C
Das sollte dein Script um einiges beschleunigen.

EDIT: In diesem Fall von 47 Taktzyklen bei Peek/Poke auf 15 Taktzyklen mit der Strukturvariante
Vielen dank! scheint wirklich schneller zu sein ich dachte immer das Peek/Poke genau so schnell wäre.
Antworten