ASM Endian Swapper

Für allgemeine Fragen zur Programmierung mit PureBasic.
Benutzeravatar
KeyKon
Beiträge: 1412
Registriert: 10.09.2004 20:51
Computerausstattung: Laptop: i5 2,8 Ghz, 16GB DDR3 RAM, GeForce 555GT 2GB VRAM
PC: i7 4,3 Ghz, 32GB DDR3 RAM, GeForce 680 GTX 4GB VRAM
Win10 x64 Home/Prof
PB 5.30 (64bit)
Wohnort: Ansbach
Kontaktdaten:

ASM Endian Swapper

Beitrag von KeyKon »

Da ich nicht wirklich Ahnung von ASM hab und mir mehr oder weniger auf gut Glück hier und da was zusammenkopiert hab,
wollte ich nur mal kurz nachfragen ob Folgendes sowohl für 32bit/64bit als auch Win/Linux zuverlässig funktioniert:

Code: Alles auswählen

EnableExplicit
EnableASM

Procedure.w EndianW(val.w)
  !MOV ax,word[p.v_val]
  !XCHG al, ah
  ProcedureReturn
EndProcedure

Procedure.l Endian(val.l)
  !MOV Eax,dword[p.v_val]
  !BSWAP Eax
  ProcedureReturn
EndProcedure

CompilerIf #PB_Compiler_Processor=#PB_Processor_x64
  Procedure.q EndianQ(val.q)
    !MOV rax,qword[p.v_val]
    !BSWAP rax
    ProcedureReturn
  EndProcedure
CompilerElse
  Procedure.q EndianQ(val.q)
    !MOV Eax,dword[p.v_val]
    !MOV Edx,dword[p.v_val+4]
    !BSWAP Eax
    !BSWAP Edx
    !MOV dword[p.v_val+4],Eax
    !MOV dword[p.v_val],Edx
    ProcedureReturn val
  EndProcedure
CompilerEndIf
Gewünschte Funktion sollte denke ich klar sein.


Dazu hätte ich noch zwei Fragen:
Woher weiß der Compiler welches Register(?)/Variable er bei ProcedureReturn zurückgeben soll.
Warum werden immer volle 8 Byte zurückgeben, so dass ich mit einer passenden Variablengröße "zurechtstutzen" muss? Sollte die Deklaration der Prozeduren nicht sicherstellen dass sowas nicht passiert? Oder wird das beim nutzen von ASM bewusst nicht gemacht um Performance zu sparen?

Code: Alles auswählen

Define word.w, long.l, quad.q

;Geht nicht:
Debug EndianW(EndianW(-1233))
Debug Endian (Endian (-1234))

quad = EndianW(EndianW(-1233))
Debug quad
quad = Endian (Endian (-1234))
Debug quad


;Geht:
Debug EndianQ(EndianQ(-1235))

word = EndianW(EndianW(-1233))
Debug word
long = Endian (Endian (-1234))
Debug long
quad = EndianQ(EndianQ(-1235))
Debug quad
LG KeyKon
(\/) (°,,,°) (\/)
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7028
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: ASM Endian Swapper

Beitrag von STARGÅTE »

Sry muss meinen Beitrag selbst korrigieren:

> Woher weiß der Compiler welches Register(?)/Variable er bei ProcedureReturn zurückgeben soll.

Er gibt immer den RAX bzw. EAX zurück, wenn kein Wert/Variable nach ProcedureReturn kommt.

>Warum werden immer volle 8 Byte zurückgeben, so dass ich mit einer passenden Variablengröße "zurechtstutzen" muss? Sollte die Deklaration der Prozeduren nicht sicherstellen dass sowas nicht passiert? Oder wird das beim nutzen von ASM bewusst nicht gemacht um Performance zu sparen?

Ich habe jetzt einen Test gemacht der das Problem behebt, ohne ASM

Code: Alles auswählen

Procedure.w EndianW(val.w)
	ProcedureReturn (val>>8&$FF) | (val<<8&$FF00)
EndProcedure

Procedure.l EndianL(val.l)
	ProcedureReturn (val>>24&$FF) | (val>>8&$FF00) | (val<<8&$FF0000) | (val<<24&$FF000000)
EndProcedure

Procedure.q EndianQ(val.q)
	ProcedureReturn (EndianL(val>>32)&$FFFFFFFF) | (EndianL(val&$FFFFFFFF)<<32)
EndProcedure

Debug EndianW(EndianW(-1233))
Debug EndianL(EndianL(-1234))
Debug EndianQ(EndianQ(-1235))
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
Benutzeravatar
KeyKon
Beiträge: 1412
Registriert: 10.09.2004 20:51
Computerausstattung: Laptop: i5 2,8 Ghz, 16GB DDR3 RAM, GeForce 555GT 2GB VRAM
PC: i7 4,3 Ghz, 32GB DDR3 RAM, GeForce 680 GTX 4GB VRAM
Win10 x64 Home/Prof
PB 5.30 (64bit)
Wohnort: Ansbach
Kontaktdaten:

Re: ASM Endian Swapper

Beitrag von KeyKon »

> Er gibt immer den RAX bzw. EAX zurück, wenn kein Wert/Variable nach ProcedureReturn kommt.

Ah ok, das erklärt ja eigentlich alles, auch warum Debug verwirrt wird.

Die Version mit dem Bit-Shiften hatte ich ursprünglich auch so ähnlich genutzt. Ich wollte aber noch etwas Speed rauspressen, weil beim Bitshiften ist gerade die Quad-Version recht behäbig. Dummerweise hab ich eben die Funktion zum testen wie gezeigt direkt hinter ein Debug geschrieben wodurch ich dann bestimmt eine Stunde gerätselt hab wieso das ASM Zeugs bei negativen Zahlen nicht funktioniert^^

LG KeyKon
(\/) (°,,,°) (\/)
Antworten