Hex 2 Binary

Just starting out? Need help? Post your questions and find answers here.
wayne-c
Enthusiast
Enthusiast
Posts: 337
Joined: Tue Jun 08, 2004 10:29 am
Location: Zurich, Switzerland

Hex 2 Binary

Post by wayne-c »

I have an image as a hex-encoded string. How can I convert it back to binary?

Code: Select all

481830010FFD8FFE000104A46494600010201004800480000FFE11CB24578696600004D4D0......
As you walk on by, Will you call my name? Or will you walk away?
User avatar
Michael Vogel
Addict
Addict
Posts: 2797
Joined: Thu Feb 09, 2006 11:27 pm
Contact:

Re: Hex 2 Binary

Post by Michael Vogel »

Do you need the byte values or a binary string?
wayne-c
Enthusiast
Enthusiast
Posts: 337
Joined: Tue Jun 08, 2004 10:29 am
Location: Zurich, Switzerland

Re: Hex 2 Binary

Post by wayne-c »

Michael Vogel wrote:Do you need the byte values or a binary string?
Hey Hichael thank you for your reply. I need a *Buffer to be able to save the originial image file to disk.
As you walk on by, Will you call my name? Or will you walk away?
User avatar
HeX0R
Addict
Addict
Posts: 1189
Joined: Mon Sep 20, 2004 7:12 am
Location: Hell

Re: Hex 2 Binary

Post by HeX0R »

Code: Select all

Procedure Hex2Mem(HexString.s)
	Protected *Buffer, i, Size, *b.BYTE
	
	Size    = Len(HexString) / 2
	*Buffer = AllocateMemory(Size)
	*b      = *Buffer
	For i = 0 To Size - 1
		*b\b = Val("$" + Mid(HexString, i * 2 + 1, 2))
		*b + 1
	Next i
	
	ProcedureReturn *Buffer
EndProcedure


a$ = "481830010FFD8FFE000104A46494600010201004800480000FFE11CB24578696600004D4D0"
*b = Hex2Mem(a$)
For i = 0 To MemorySize(*b) - 1
	Debug RSet(Hex(PeekB(*b + i), #PB_Byte), 2, "0")
Next i
User avatar
Mijikai
Addict
Addict
Posts: 1517
Joined: Sun Sep 11, 2016 2:17 pm

Re: Hex 2 Binary

Post by Mijikai »

infratec
Always Here
Always Here
Posts: 7583
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: Hex 2 Binary

Post by infratec »

More cryptic, but faster:

Code: Select all

EnableExplicit

Procedure.i Hex2Mem(HexString$)
 
  Protected *Buffer, *b.BYTE, *c.Character, b.a
 
 
  *Buffer = AllocateMemory(Len(HexString$) / 2, #PB_Memory_NoClear)
  If *Buffer
    *b = *Buffer
    *c = @HexString$
   
    While *c\c
      b = *c\c - '0'
      If b > 9
        b - 7
        If b > 15
          b - 32
        EndIf
      EndIf
      *b\b  = b << 4
      *c + 2
     
      b = *c\c - '0'
      If b > 9
        b - 7
        If b > 15
          b - 32
        EndIf
      EndIf
      *b\b | b
      *c + 2
     
      *b + 1
    Wend
  EndIf
 
  ProcedureReturn *Buffer
 
EndProcedure


Define a$, *b

a$ = "4a1830010FFD8FFE000104A46494600010201004800480000FFE11CB24578696600004D4D0"
*b = Hex2Mem(a$)
If *b
  ShowMemoryViewer(*b, MemorySize(*b))
  FreeMemory(*b)
EndIf
Last edited by infratec on Fri May 15, 2020 1:56 pm, edited 1 time in total.
User avatar
NicTheQuick
Addict
Addict
Posts: 1504
Joined: Sun Jun 22, 2003 7:43 pm
Location: Germany, Saarbrücken
Contact:

Re: Hex 2 Binary

Post by NicTheQuick »

If you want to use infratec's version keep in mind that it only works with uppercase letters in your HEX string.
The english grammar is freeware, you can use it freely - But it's not Open Source, i.e. you can not change it or publish it in altered way.
infratec
Always Here
Always Here
Posts: 7583
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: Hex 2 Binary

Post by infratec »

updated the code above for lowercase letters too. :wink:
User avatar
NicTheQuick
Addict
Addict
Posts: 1504
Joined: Sun Jun 22, 2003 7:43 pm
Location: Germany, Saarbrücken
Contact:

Re: Hex 2 Binary

Post by NicTheQuick »

@infratec:
Do you like bit fiddling? I've got something for you:

Code: Select all

b = (*c\c | %100000) - '0' - (*c\c >> 6) * 39
It replaces all this:

Code: Select all

      b = *c\c - '0'
      If b > 9
        b - 7
        If b > 15
          b - 32
        EndIf
      EndIf
But I don't know if it is faster. It's just more fancy. :lol:

Edit:
Even better:

Code: Select all

b = (*c\c & %1111) + (*c\c >> 6) * 9
The english grammar is freeware, you can use it freely - But it's not Open Source, i.e. you can not change it or publish it in altered way.
User avatar
Mijikai
Addict
Addict
Posts: 1517
Joined: Sun Sep 11, 2016 2:17 pm

Re: Hex 2 Binary

Post by Mijikai »

My try:

Code: Select all

EnableExplicit

Procedure.i Hex2Bin(Input.s);upper case & unicode only!
  Protected *dat
  Protected *bin.Ascii
  Protected *str.Unicode
  Protected *cmp.Long
  Protected *tbl.Long
  Protected siz.i
  Protected pos.i
  siz = Len(Input)
  If siz
    If Not Mod(siz,2)
      siz >> 1
      *bin = AllocateMemory(siz)
      If *bin
        *dat = *bin
        *str = @Input
        *cmp = *str
        Repeat
          For pos = 0 To 255
            *tbl = ?hex2bin_table + (pos << 2)
            If *tbl\l = *cmp\l
              *bin\a = pos
              *bin + 1
              Break
            EndIf
          Next
          *str + 2
          *cmp + 4
        Until *str\u = #Null
      EndIf
    EndIf
  EndIf
  If *dat 
    If (*bin - *dat) = siz
      ProcedureReturn *dat
    Else
      FreeMemory(*dat)
      ProcedureReturn #Null
    EndIf
  EndIf
  ProcedureReturn #Null
  hex2bin_table:
  !du '00','01','02','03','04','05','06','07','08','09','0A','0B','0C','0D','0E','0F'
  !du '10','11','12','13','14','15','16','17','18','19','1A','1B','1C','1D','1E','1F'
  !du '20','21','22','23','24','25','26','27','28','29','2A','2B','2C','2D','2E','2F'
  !du '30','31','32','33','34','35','36','37','38','39','3A','3B','3C','3D','3E','3F'
  !du '40','41','42','43','44','45','46','47','48','49','4A','4B','4C','4D','4E','4F'
  !du '50','51','52','53','54','55','56','57','58','59','5A','5B','5C','5D','5E','5F'
  !du '60','61','62','63','64','65','66','67','68','69','6A','6B','6C','6D','6E','6F'
  !du '70','71','72','73','74','75','76','77','78','79','7A','7B','7C','7D','7E','7F'
  !du '80','81','82','83','84','85','86','87','88','89','8A','8B','8C','8D','8E','8F'
  !du '90','91','92','93','94','95','96','97','98','99','9A','9B','9C','9D','9E','9F'
  !du 'A0','A1','A2','A3','A4','A5','A6','A7','A8','A9','AA','AB','AC','AD','AE','AF'
  !du 'B0','B1','B2','B3','B4','B5','B6','B7','B8','B9','BA','BB','BC','BD','BE','BF'
  !du 'C0','C1','C2','C3','C4','C5','C6','C7','C8','C9','CA','CB','CC','CD','CE','CF'
  !du 'D0','D1','D2','D3','D4','D5','D6','D7','D8','D9','DA','DB','DC','DD','DE','DF'
  !du 'E0','E1','E2','E3','E4','E5','E6','E7','E8','E9','EA','EB','EC','ED','EE','EF'
  !du 'F0','F1','F2','F3','F4','F5','F6','F7','F8','F9','FA','FB','FC','FD','FE','FF'
EndProcedure

Global hstr.s = "FF0001"
Global *binary

*binary = Hex2Bin(hstr)

If *binary
  ShowMemoryViewer(*binary,MemorySize(*binary))
EndIf

End
The code also checks if in- and output is valid.
User avatar
NicTheQuick
Addict
Addict
Posts: 1504
Joined: Sun Jun 22, 2003 7:43 pm
Location: Germany, Saarbrücken
Contact:

Re: Hex 2 Binary

Post by NicTheQuick »

@Mijikai: Without testing it I assume that your method will be a lot slower because you do a For-loop for every byte, so the worst case scenario makes will loop 256 times by byte and on average 128 times which is still too much.
The english grammar is freeware, you can use it freely - But it's not Open Source, i.e. you can not change it or publish it in altered way.
JagV12
New User
New User
Posts: 9
Joined: Sat Jun 22, 2019 11:28 am

Re: Hex 2 Binary

Post by JagV12 »

I love "*b.BYTE, *c.Character" declaration and *c\c and *b\b usage but didn't know about it. The role is obvious here but is there a place I should read to learn more about it ?
breeze4me
Enthusiast
Enthusiast
Posts: 633
Joined: Thu Mar 09, 2006 9:24 am
Location: S. Kor

Re: Hex 2 Binary

Post by breeze4me »

2 asm procedures and 1 PB procedure.

Code: Select all

Procedure IsValidHexString(*HexSrting.Character)
  
  If MemoryStringLength(*HexSrting, #PB_Unicode) % 2 Or *HexSrting = 0
    ProcedureReturn 0
  EndIf
  
  While *HexSrting\c
    If *HexSrting\c > 'f' Or *HexSrting\c < '0'
      ProcedureReturn 0
    EndIf
    
    If *HexSrting\c > '9' And *HexSrting\c < 'A'
      ProcedureReturn 0
    EndIf
    
    If *HexSrting\c > 'F' And *HexSrting\c < 'a'
      ProcedureReturn 0
    EndIf
    
    *HexSrting + SizeOf(Character)
  Wend
  
  ProcedureReturn 1
EndProcedure

Procedure HexStringToBinData_ASM1(*InHexSrting, *OutBinData)
  CompilerIf Not #PB_Compiler_InlineAssembly
    EnableASM
    ___temp___:
  CompilerEndIf
  
  CompilerIf #PB_Compiler_Processor = #PB_Processor_x86
    MOV edx, *OutBinData
    MOV eax, *InHexSrting
  CompilerElse
    MOV rdx, *OutBinData
    MOV rax, *InHexSrting
  CompilerEndIf
  
  CompilerIf Defined(___temp___, #PB_Label)
    DisableASM
  CompilerEndIf
  
  CompilerIf #PB_Compiler_Processor = #PB_Processor_x86
    !PUSH ebx
    !PUSH esi
    !PUSH edi
    !MOV edi, 9
    
    !@@:
    ;1st character
    !MOVZX ebx, word [eax]
    !TEST ebx, ebx
    !JZ @f
    
    ;(c & %1111) + (c >> 6) * 9
    !XOR ecx, ecx
    !TEST ebx, 0x40
    !CMOVNZ ecx, edi
    !ADD ebx, ecx
    
    !SHL ebx, 4
    
    ;2nd character
    !MOVZX esi, word [eax + 2]
    
    ;(c & %1111) + (c >> 6) * 9
    !XOR ecx, ecx
    !TEST esi, 0x40
    !CMOVNZ ecx, edi
    !AND esi, 0x0F
    !ADD esi, ecx
    
    !OR ebx, esi
    
    ;save the combined value to *OutBinData
    !MOV byte [edx], bl
    
    ;for the next 2 characters
    !ADD eax, 4
    !ADD edx, 1
    !JMP @r
    
    !@@:
    !POP edi
    !POP esi
    !POP ebx
    
  CompilerElse  ;x64
    !PUSH rbx
    !MOV r9, 9
    
    !@@:
    ;1st character
    !MOVZX rbx, word [rax]
    !TEST ebx, ebx
    !JZ @f
    
    ;(c & %1111) + (c >> 6) * 9
    !XOR rcx, rcx
    !TEST ebx, 0x40
    !CMOVNZ rcx, r9
    !ADD ebx, ecx
    
    !SHL ebx, 4
    
    ;2nd character
    !MOVZX r8, word [rax + 2]
    
    ;(c & %1111) + (c >> 6) * 9
    !XOR rcx, rcx
    !TEST r8, 0x40
    !CMOVNZ rcx, r9
    !AND r8, 0x0F
    !ADD r8, rcx
    
    !OR rbx, r8
    
    ;save the combined value to *OutBinData
    !MOV byte [rdx], bl
    
    ;for the next 2 characters
    !ADD rax, 4
    !ADD rdx, 1
    !JMP @r
    
    !@@:
    !POP rbx
  CompilerEndIf
  
  ProcedureReturn
EndProcedure

Procedure HexStringToBinData_ASM2(*InHexSrting, *OutBinData)
  CompilerIf Not #PB_Compiler_InlineAssembly
    EnableASM
    ___temp___:
  CompilerEndIf
  
  CompilerIf #PB_Compiler_Processor = #PB_Processor_x86
    MOV ecx, *InHexSrting
    MOV edx, *OutBinData
  CompilerElse
    MOV rcx, *InHexSrting
    MOV rdx, *OutBinData
  CompilerEndIf
  
  CompilerIf Defined(___temp___, #PB_Label)
    DisableASM
  CompilerEndIf
  
  CompilerIf #PB_Compiler_Processor = #PB_Processor_x86
    !PUSH esi
    !PUSH ebx
    
    !MOV ebx, ___lb_HexTable
    
    !@@:
    ;1st character
    !MOVZX eax, word [ecx]
    !TEST eax, eax
    !JZ @f
    
    !XLATB
    !SHL eax, 4
    !MOV esi, eax
    
    ;2nd character
    !MOVZX eax, word [ecx + 2]
    
    !XLATB
    !OR eax, esi
    
    ;save the combined value to *OutBinData
    !MOV byte [edx], al
    
    ;for the next 2 characters
    !ADD ecx, 4
    !ADD edx, 1
    !JMP @r
    
    !@@:
    !POP ebx
    !POP esi
    
  CompilerElse  ;x64
    !MOV r9, ___lb_HexTable
    
    !@@:
    ;1st character
    !MOVZX rax, word [rcx]
    !TEST eax, eax
    !JZ @f
    
    !MOV al, byte [r9 + rax]
    !SHL eax, 4
    !MOV r8, rax
    
    ;2nd character
    !MOVZX rax, word [rcx + 2]
    
    !MOV al, byte [r9 + rax]
    !OR rax, r8
    
    ;save the combined value to *OutBinData
    !MOV byte [rdx], al
    
    ;for the next 2 characters
    !ADD rcx, 4
    !ADD rdx, 1
    !JMP @r
    
    !@@:
  CompilerEndIf
  
  ProcedureReturn
EndProcedure

Procedure HexStringToBinData_PB(*InHexSrting.Character, *OutBinData.Byte)
  
  Structure ByteArray
    b.b[0]
  EndStructure
  
  Protected *Table.ByteArray = ?___lb_HexTable
  Protected v
  
  While *InHexSrting\c
    
    v = *InHexSrting\c
    *InHexSrting + 2
    
    *OutBinData\b = (*Table\b[v] << 4) | *Table\b[*InHexSrting\c]
    
    *InHexSrting + 2
    *OutBinData + 1
  Wend
  
  ProcedureReturn
EndProcedure

DataSection
  ___lb_HexTable:
  !___lb_HexTable:
  Data.q 0, 0, 0, 0, 0, 0
  Data.b 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
  Data.b 0, 0, 0, 0, 0, 0, 0
  Data.b 10, 11, 12, 13, 14, 15
  Data.q 0, 0, 0
  Data.b 0, 0
  Data.b 10, 11, 12, 13, 14, 15
EndDataSection



*m = AllocateMemory(10240)
FillMemory(*m, 1024, $11)

a$ = "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F" +
     "404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F" +
     "808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF" +
     "C0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF" +
     "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f" +
     "404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f" +
     "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebf" +
     "c0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"


If IsValidHexString(@a$)
  
  ;HexStringToBinData_ASM1(@a$, *m)
  ;HexStringToBinData_ASM2(@a$, *m)
  HexStringToBinData_PB(@a$, *m)
  
  ShowMemoryViewer(*m, 1024)
  
EndIf
[/size]


Edit: a bug is fixed.
!MOVZX rbx, word [eax] --> !MOVZX rbx, word [rax]
:mrgreen:
User avatar
mk-soft
Always Here
Always Here
Posts: 6207
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: Hex 2 Binary

Post by mk-soft »

I love "*b.BYTE, *c.Character" declaration and *c\c and *b\b usage but didn't know about it. The role is obvious here but is there a place I should read to learn more about it ?
Is top secret ...

Not find in PB help
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
infratec
Always Here
Always Here
Posts: 7583
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: Hex 2 Binary

Post by infratec »

I'm a whisteblower :wink:

You can define structures as you want.
The (hidden) point is:
The structures for the basic variable types (Character, Integer, Byte ...) are already defined.

Code: Select all

Structure ByteStructue
  byte.a
EndStructure


Define Long.l, i.i
Define *Byte.ByteStructue

Long = $12345678

*Byte = @Long
For i = 0 To 3
  Debug Hex(*Byte\byte)
  *Byte + 1
Next i
Post Reply