Page 1 of 1
Read bytes in Motorola format
Posted: Thu Jul 31, 2003 9:49 pm
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
Posted: Thu Jul 31, 2003 10:49 pm
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.
Posted: Thu Jul 31, 2003 10:56 pm
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
Posted: Thu Jul 31, 2003 11:06 pm
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)
Posted: Thu Jul 31, 2003 11:53 pm
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)
Posted: Thu Jul 31, 2003 11:53 pm
by Flype
thanx for all your answers, that's great
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 )
Posted: Thu Jul 31, 2003 11:58 pm
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

Posted: Fri Aug 01, 2003 12:19 am
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
Posted: Fri Aug 01, 2003 12:59 am
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:
Posted: Fri Aug 01, 2003 1:26 am
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
Posted: Fri Aug 01, 2003 6:45 am
by Psychophanta
Nice info
Thanx! Timo
AL
Nice
Posted: Sat Aug 02, 2003 5:54 am
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