Something I've been struggling with is getting an ASM implementation of a synch safe integer encoding. More or less on ID3V2 tags, it requires integers that are MSB with the 7th bit not in use on each byte. For instance:
HEX Enc Dec
255020 002CE403 000F482C 002CE403
I had the idea to shift on each part, but in research, I found this nice solution by dedndave from one of the old MASM forums. Only thing that it was missing was the MSB thing, which I fixed.
function size_decodeh2(insize: DWord): DWord;
// dedndave masm32
asm
bswap eax
mov ecx,eax
shl al,1
shl ax,1
shl eax,1
and eax,00FFFFF8h // don't understand what this does?
and ecx,7F000000h
or eax,ecx
shr eax,3
end;
Other than the line I marked, I understand this fully. However, I'm trying to encode, which seems to be doable if I reverse this logic, but I'm not having much luck coming up with the algo to do it. Any thoughts or hints?
that line clears the high byte of EAX
i don't remember writing that code - lol
maybe you could link us to the original post ?
oh - i found it
Hi,
The line you marked clears the high byte so it can be retrieved
from ECX with the next two lines.
QuoteHowever, I'm trying to encode, which seems to be doable if I reverse this logic, but I'm not having much luck coming up with the algo to do it. Any thoughts or hints?
Maybe something like the following?
; Enter with value in EAX.
SHL EAX,3
MOV ECX,EAX ; Save "high" byte.
AND ECX,0FF000000H ; Only high byte is good.
AND EAX,000FFFFFFH ; High byte is in ECX.
SHR EAX,1
OR ECX,EAX ; Save Next byte.
AND ECX,0FFFF0000H ; Two high bytes good.
AND EAX,00000FFFFH ; High bytes in ECX.
SHR EAX,1
OR ECX,EAX ; Save Next byte.
AND ECX,0FFFFFF00H ; Three high bytes good.
AND EAX,0000000FFH ; High bytes in ECX.
SHR EAX,1
OR EAX,ECX ; Retrieve high bytes.
BSWAP EAX
HTH,
Steve N.
Quote from: dedndave on August 29, 2015, 07:08:46 AM
maybe you could link us to the original post ?
http://www.masmforum.com/board/index.php?topic=14509.0
Quote from: dedndave on August 29, 2015, 07:08:46 AM
that line clears the high byte of EAX
I knew that, but didn't see where it fit in on the algo. Now that I see that in writing and think on it, I see how it fits now.
Now that I got my mind wrapped around it, I saw I had a misunderstanding about what one of the assembler instructions does to the registers. I ended up finishing the encoding piece the original way I had in mind. It seems to work properly in my testing code and benchmarks well. Sharing here:
function size_encodeh3(insize: DWord): DWord;
// by Glenn9999 with ideas stemming from this thread.
asm
SHL EAX, 3
MOV ECX, EAX
AND ECX, $FF000000
AND EAX, $00FFFFFF
SHR EAX, 1
OR EAX, ECX
SHR AX, 1
SHR AL, 1
BSWAP EAX
end;
Thanks for all the help!
I wrote one a long time ago, not very efficient but I wasn't too concerned as it is not a bottleneck since it is only used in the tag reader. It was pretty much a hack that I never bothered to fix up. (GoAsm syntax)
DecodeSynchSafe FRAME SSVAR
LOCAL SSCF1 :B
LOCAL SSCF2 :B
LOCAL SSCF3 :B
LOCAL SSBYTE1 :B
LOCAL SSBYTE2 :B
LOCAL SSBYTE3 :B
LOCAL SSBYTE4 :B
mov eax,[SSVAR]
mov [SSBYTE4],al
mov [SSBYTE3],ah
bswap eax
mov [SSBYTE1],al
mov [SSBYTE2],ah
mov al,[SSBYTE2]
mov [SSCF1],al
and B[SSCF1],1
shl B[SSCF1],7
mov al,[SSBYTE3]
mov [SSCF2],al
and B[SSCF2],3
shl B[SSCF2],6
mov al,[SSBYTE4]
mov [SSCF3],al
and B[SSCF3],7
shl B[SSCF3],5
; Build Bytes from data
;
mov al,[SSCF1]
or [SSBYTE1],al
shr B[SSBYTE2],1
mov al,[SSCF2]
or [SSBYTE2],al
shr B[SSBYTE3],2
mov al,[SSCF3]
or [SSBYTE3],al
shr B[SSBYTE4],3
; Build DWORD from bytes
;
mov al,[SSBYTE1]
mov ah,[SSBYTE2]
bswap eax
mov al,[SSBYTE4]
mov ah,[SSBYTE3]
bswap eax
ret
ENDF