4

我正在尝试解码 masm 中的十六进制二进制字符串,起初我尝试了 htodw 但解码不正确,所以我尝试了 hex2bin 并且这个似乎解码得很好,但我遇到了空字节的问题。十六进制编码的字符串将在第一个空字节 (0x00) 处终止。

这是我的代码示例:

.486
.model  flat, stdcall
option  casemap :none

include \masm32\include\windows.inc
include \masm32\include\masm32.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\masm32.lib
includelib \masm32\lib\user32.lib

.data
; this string is "test(NULL BYTE)test", but the messagebox only shows "test"
var_hex db "746573740074657374",0 

multitable \
    db 0,0,0,0,0,0,0,0,0,0,2,0,0,2,0,0
    db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
    db 2,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0
    db 1,1,1,1,1,1,1,1,1,1,0,3,0,0,0,0
    db 0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0
    db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
    db 0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0
    db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
    db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
    db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
    db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
    db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
    db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
    db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
    db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
    db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0

    ; 0 = unacceptable character
    ; 1 = acceptable characters   (0 to 9, A to F, a to f)
    ; 2 = ignored characters      (space, minus and CRLF)
    ; 3 = comment character       ( ; )

    ; 1st offset table
    db 00h,10h,20h,30h,40h,50h,60h,70h,80h,90h,0,0,0,0,0,0      ; 63
    db 00h,0A0h,0B0h,0C0h,0D0h,0E0h,0F0h,0,0,0,0,0,0,0,0,0      ; 79
    db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0                          ; 95
    db 00h,0A0h,0B0h,0C0h,0D0h,0E0h,0F0h

    ; 2nd offset table
    db 00h,01h,02h,03h,04h,05h,06h,07h,08h,09h,0,0,0,0,0,0      ; 63
    db 00h,0Ah,0Bh,0Ch,0Dh,0Eh,0Fh,0,0,0,0,0,0,0,0,0            ; 79
    db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0                          ; 95
    db 00h,0Ah,0Bh,0Ch,0Dh,0Eh,0Fh

    ; add 256 for allowable character table
    ; sub 48 from 1st offset table
    ; add 7 for the second BYTE

.data?
var dd ?

.code
main:
    Invoke hex2bin, addr var_hex, addr var

    Invoke MessageBoxA,0,addr var,0,0

    invoke ExitProcess, 0


    ; hex2bin
    align 4

    hex2bin proc src:DWORD,dst:DWORD

    comment * ---------------------------------
            EAX and EBX are unused in loop code
            --------------------------------- *

        push ebx
        push esi
        push edi
        push ebp

        mov esi, src
        mov edi, dst

        xor ebp, ebp

        jmp h2b                             ; mispredicted only once

      align 4
      stripcomment:
        add esi, 1
        cmp BYTE PTR [esi], 10
        jb zerofound                        ; < 10 = 0
        jne stripcomment                    ; loop if not 10
      align 4
      pre:
        add esi, 1
      align 4
      h2b:
        movzx ebp, BYTE PTR [esi]           ; zero extend 1st byte into EBP
        cmp BYTE PTR [ebp+multitable], 2    ; 1st compare short circuit on ignored characters
        je pre                              ; predicted backwards
        movzx edx, BYTE PTR [esi+1]         ; zero extend 2nd BYTE into EDX
        ja stripcomment                     ; predicted backwards

        mov cl, [ebp+multitable+208]        ; load 1st character into CL from 2nd table
        add cl, [edx+multitable+263]        ; add value of second character from 3rd table
        cmp BYTE PTR [ebp+multitable], 0    ; exit on error or ZERO
        je error1                           ; mispredicted only once

        mov [edi], cl                       ; write BYTE to output buffer
        add esi, 2
        add edi, 1
        cmp BYTE PTR [edx+multitable], 1    ; test if second byte is allowable character
        je h2b                              ; predicted backwards

      error2:
        mov ecx, 2                          ; error 2 = illegal character
        jmp exitproc
      error1:
        test ebp, ebp                       ; test if byte is terminator
        jz zerofound
        mov ecx, 1                          ; error 1 = non matching hex character pairs
        jmp exitproc
      zerofound:
        xor ecx, ecx                        ; no error 0

      exitproc:

        pop ebp                             ; restore EBP before using stack parameter
        sub edi, dst
        mov eax, edi

        pop edi
        pop esi
        pop ebx

        ret

    hex2bin endp

end main

无论它包含什么类型的字符,我如何解码任何类型的十六进制编码字符串?

4

2 回答 2

0

无需使用多个查找表!

所以只使用一个带有返回码的 256 字节表:

; 0..0x0F = char to bin value
; 0x80 = unacceptable character
; 0x81 = ignored characters      (space, minus and CRLF)
; 0x82 = comment character        ( ; )

那应该可以解决您的问题!

编辑:添加代码

将表更改为:

multitable \
    db 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x81,0x80,0x80,0x81,0x80,0x80
    db 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80
    db 0x81,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x81,0x80,0x80
    db 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x80,0x82,0x80,0x80,0x80,0x80
    db 0x80,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80
    db 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80
    db 0x80,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80
    db 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80
    db 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80
    db 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80
    db 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80
    db 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80
    db 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80
    db 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80
    db 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80
    db 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80

现在您可以一次获取 value 和 character 属性:

        movzx ebp, BYTE PTR [esi]           ; zero extend 1st byte into EBP
        mov   cl, [ebp+multitable]          ; convert char to value or attribute
        cmp   cl, 0x0F                      ; if cl > 0xF then attribute
        ja    AttributeFind                 ; resolve Attribute
                                            ; in cl is converted char from 0..15
        inc   esi                           ; covert next char
        movzx ebp, BYTE PTR [esi]           ; zero extend second byte into EBP
        mov   ch, [ebp+multitable]          ; convert char to value or attribute
        cmp   ch, 0x0F                      ; if ch > 0xF then attribute
        ja    AttributeFind                 ; resolve Attribute
                                            ; in ch is converted char from 0..15
;put together both nibbles in cl and ch
        shl   ch, 4                         ;shift ch left by 4
        or    cl, ch
;store byte result
        mov   BYTE PTR [edi], cl
于 2011-07-28T09:38:07.250 回答
0

我前段时间这样做过:

include \masm32\include\masm32rt.inc

.data
var_hex db "746573740074657374",0 

.data?
out_hex db ?

.code
String2Hex proc offstring:DWORD, outstring:DWORD
    mov eax, offstring
    xor ecx, ecx
    mov ebx, outstring
    .repeat
        mov dh, byte ptr ds:[eax]
        mov dl, byte ptr ds:[eax+1]
        .if dl > 39h
            sub dl, 37h
        .else
            sub dl, 30h
        .endif
        .if dh > 39h
            sub dh, 37h
        .else
            sub dh, 30h
        .endif
        shl dl, 4
        shr dx, 4
        mov byte ptr ds:[ebx+ecx], dl
        inc ecx
        add eax, 2
    .until byte ptr ds:[eax-1]==0
    mov eax, ecx
    ret
String2Hex endp

main:
    Invoke String2Hex, addr var_hex, addr out_hex
    Invoke MessageBoxA,0,addr out_hex,0,0
    invoke ExitProcess, 0
End main

我做了一些修改,就像你的测试代码一样。

于 2011-07-28T14:15:11.163 回答