Read bytes in Motorola format

Share your advanced PureBasic knowledge/code with the community.
User avatar
Flype
Addict
Addict
Posts: 1542
Joined: Tue Jul 22, 2003 5:02 pm
Location: In a long distant galaxy

Read bytes in Motorola format

Post by Flype »

Code updated for 5.20+

Hello,

My question is about data stored in files in Motorola format, NOT Intel.
In this case we have to byteswap to get each values, ie: Bytes 1,2,3,4 need to become 4,3,2,1.
I need to interpret such files so i've written a procedure :

Code: Select all

Procedure PeekLMotorola( address.l )
  
  ; address of value in Motorola format -> value in Intel format
  
  b1.l = PeekB( address+0 ) & 255
  b2.l = PeekB( address+1 ) & 255
  b3.l = PeekB( address+2 ) & 255
  b4.l = PeekB( address+3 ) & 255
  ProcedureReturn (b1<<24) + (b2<<16) + (b3<<8) + b4
  
EndProcedure

; An example of use...

a.l
PokeB( @a+0, $10 )
PokeB( @a+1, $10 )
PokeB( @a+2, $20 )
PokeB( @a+3, $20 )
Debug PeekLMotorola( @a )
Is it well coded, how could it done in asm (for speedup) ?
Thanx
No programming language is perfect. There is not even a single best language.
There are only languages well suited or perhaps poorly suited for particular purposes. Herbert Mayer
Pupil
Enthusiast
Enthusiast
Posts: 715
Joined: Fri Apr 25, 2003 3:56 pm

Post by Pupil »

You could do it like this with structures:

Code: Select all

Structure LongOfBytes
  b1.b
  b2.b
  b3.b
  b4.b
EndStructure

Procedure Lower2Upper(*value.LongOfBytes)
  *ptr.LongOfBytes = @result.l
  *ptr\b4 = *value\b1
  *ptr\b3 = *value\b2
  *ptr\b2 = *value\b3
  *ptr\b1 = *value\b4
  procedurereturn result
endprocedure

a.l = $10203040
debug hex(a)+", "+hex(Lower2Upper(@a))
It's not assembly but it should perhaps be a bit faster than your version.
User avatar
Psychophanta
Always Here
Always Here
Posts: 5153
Joined: Wed Jun 11, 2003 9:33 pm
Location: Anare
Contact:

Post by Psychophanta »

For example:

Code: Select all

a=$40506070

!ror word [v_a],8
!ror word [v_a+2],8
!ror dword [v_a],16

MessageRequester("",Hex(a),0)

AL
Pupil
Enthusiast
Enthusiast
Posts: 715
Joined: Fri Apr 25, 2003 3:56 pm

Post by Pupil »

Psychophanta wrote:For example:

Code: Select all

a=$40506070

!ror word [v_a],8
!ror word [v_a+2],8
!ror dword [v_a],16

MessageRequester("",Hex(a),0)

AL
That's a nice one :)

if you've got a 486 cpu or higher this will also work:

Code: Select all

a.l = $10203040

!mov eax, dword[v_a]
!bswap eax
!mov dword[v_a], eax

Debug Hex(a)
freak
PureBasic Team
PureBasic Team
Posts: 5941
Joined: Fri Apr 25, 2003 5:21 pm
Location: Germany

Post by freak »

And, if you want to keep it inside a procedure, and together with
the Peeking ability, it can look like this:

Code: Select all

Procedure.l PeekLMotorola(address.l) 
  !mov eax, [esp]
  !mov eax, [eax]
  !bswap eax
  ProcedureReturn
EndProcedure

a.l = $10203040 
b.l = PeekLMotorola(@a)

Debug Hex(b)
quidquid Latine dictum sit altum videtur
User avatar
Flype
Addict
Addict
Posts: 1542
Joined: Tue Jul 22, 2003 5:02 pm
Location: In a long distant galaxy

Post by Flype »

thanx for all your answers, that's great :P
pupil you're the winner of my time test, have a look :

Code: Select all

a.l
result.s
NBTEST = 20000000

;--------------------------------------------------------

Procedure.s Resultat( proc.s, value, time.l )
  ProcedureReturn proc+" : "+Hex(value)+" in "+Str(GetTickCount_()-time)+" msecs"+Chr(10)
EndProcedure

;--------------------------------------------------------

Procedure PeekLMotorolaAddress( pValue.l )
  b1.l = PeekB( pValue   ) & 255
  b2.l = PeekB( pValue+1 ) & 255
  b3.l = PeekB( pValue+2 ) & 255
  b4.l = PeekB( pValue+3 ) & 255
  ProcedureReturn (b1<<24)+(b2<<16)+(b3<<8)+b4
EndProcedure

t=GetTickCount_()
For i=0 To NBTEST
  a = $40302010 : a = PeekLMotorolaAddress( @a )
Next
result + Resultat( "PeekLMotorolaAddress()", a, t )

;--------------------------------------------------------

Structure LongOfBytes 
  b.b[4]
EndStructure 

Procedure PeekLMotorolaStruct( *pValue.LongOfBytes )
  *ptr.LongOfBytes = @result.l
  *ptr\b[3] = *pValue\b[0]
  *ptr\b[2] = *pValue\b[1] 
  *ptr\b[1] = *pValue\b[2] 
  *ptr\b[0] = *pValue\b[3] 
  ProcedureReturn result 
EndProcedure 

t=GetTickCount_()
For i=0 To NBTEST
  a = $40302010 : a = PeekLMotorolaStruct( @a )
Next
result + Resultat( "PeekLMotorolaStruct()", a, t )

;--------------------------------------------------------

Structure LongOfBytes2
  b1.b : b2.b : b3.b : b4.b 
EndStructure 

Procedure PeekLMotorolaStruct2( *pValue.LongOfBytes2 ) 
  *ptr.LongOfBytes2 = @result.l 
  *ptr\b4 = *pValue\b1 
  *ptr\b3 = *pValue\b2 
  *ptr\b2 = *pValue\b3 
  *ptr\b1 = *pValue\b4 
  ProcedureReturn result 
EndProcedure 

t=GetTickCount_()
For i=0 To NBTEST
  a = $40302010 : a = PeekLMotorolaStruct2( @a )
Next
result + Resultat( "PeekLMotorolaStruct2()", a, t )

;--------------------------------------------------------

Procedure PeekLMotorolaASM()
  ROR word  [v_a],   8
  ROR word  [v_a+2], 8
  ROR dword [v_a],  16
EndProcedure

t=GetTickCount_()
For i=0 To NBTEST
  a = $40302010 : PeekLMotorolaASM()
Next
result + Resultat( "PeekLMotorolaASM()", a, t )

;--------------------------------------------------------

Procedure PeekLMotorolaASM2()
  MOV   EAX, dword[v_a] 
  BSWAP EAX 
  MOV   dword[v_a], EAX
EndProcedure

t=GetTickCount_()
For i=0 To NBTEST
  a = $40302010 : PeekLMotorolaASM2()
Next
result + Resultat( "PeekLMotorolaASM2()", a, t )

;--------------------------------------------------------

Procedure.l PeekLMotorolaASM3( pValue.l )
  MOV   EAX, [ESP]
  MOV   EAX, [EAX]
  BSWAP EAX
  ProcedureReturn
EndProcedure

t=GetTickCount_()
For i=0 To NBTEST
  a = $40302010 : a = PeekLMotorolaASM3(@a)
Next
result + Resultat( "PeekLMotorolaASM3()", a, t )

;--------------------------------------------------------

MessageRequester( "Timer", result, 0 )
Last edited by Flype on Fri Aug 01, 2003 12:03 am, edited 1 time in total.
No programming language is perfect. There is not even a single best language.
There are only languages well suited or perhaps poorly suited for particular purposes. Herbert Mayer
User avatar
Flype
Addict
Addict
Posts: 1542
Joined: Tue Jul 22, 2003 5:02 pm
Location: In a long distant galaxy

Post by Flype »

Procedure.l PeekLMotorola(address.l)
!mov eax, [esp]
!mov eax, [eax]
!bswap eax
ProcedureReturn
EndProcedure
obviously my prefered one as it is exactly what i expected, thanx freak :P
No programming language is perfect. There is not even a single best language.
There are only languages well suited or perhaps poorly suited for particular purposes. Herbert Mayer
Pupil
Enthusiast
Enthusiast
Posts: 715
Joined: Fri Apr 25, 2003 3:56 pm

Post by Pupil »

If you want to keep compatibility with processors prior to 486 you can use this modified version of Psychophanta's code that works very good, almost as fast as Freak's version.

Code: Select all

Procedure.l PeekLMotorola(address.l)
  MOV eax, dword [ESP]
  MOV eax, [eax]
  ROR ax, 8
  ROR eax, 16
  ROR ax, 8
  ProcedureReturn
EndProcedure
User avatar
Flype
Addict
Addict
Posts: 1542
Joined: Tue Jul 22, 2003 5:02 pm
Location: In a long distant galaxy

Post by Flype »

thanx again !

pupil or freak, in your last code, [ESP] is where the procedures args are stored ?
So is ESP the Stack Pointer ? If yes it explains why your ProcedureReturn line didn't take argument :roll:
No programming language is perfect. There is not even a single best language.
There are only languages well suited or perhaps poorly suited for particular purposes. Herbert Mayer
freak
PureBasic Team
PureBasic Team
Posts: 5941
Joined: Fri Apr 25, 2003 5:21 pm
Location: Germany

Post by freak »

ESP is the Stack pointer. [ESP] is the value at this point of the stack.
(which is the argument)

If there is more than one argument, the second one will be in [ESP+4]
the third in [ESP+8] and so on...

btw: don't POP them from the stack, as the Procedure removes them at
return

The result of a procedure is returned through EAX, that's why you can
put the result in EAX, and the just call ProcedureReturn without argument.

Timo
quidquid Latine dictum sit altum videtur
User avatar
Psychophanta
Always Here
Always Here
Posts: 5153
Joined: Wed Jun 11, 2003 9:33 pm
Location: Anare
Contact:

Post by Psychophanta »

Nice info :)

Thanx! Timo :P


AL
LJ
Enthusiast
Enthusiast
Posts: 177
Joined: Wed Apr 30, 2003 4:00 pm

Nice

Post by LJ »

Nice Purebasic Inline Assembly! I attempted to convert the code by Freak into a DLL, (the procedure assembly code the dll) but it doesn't seem possible. It would be very cool to be able to push values on and off the stack or at least store in EAX from the DLL and then be able to POP the stack or extract that value from EAX back in the main procedure. Does anyone know why Freak's code doesn't work from a DLL (are the rules different for the stack pointer when calling a DLL?) or is it something I'm doing wrong?

Lj
Post Reply