Please use an editor with syntax highlighted to view the code. The readability will be greatly enhanced. If you check the MMX command (I have commented on it), use od to trace mm0, MM1 values (corresponding to the 64-bit low of ST (0) and ST (1) can be further understood !!
Low-performing ml.exedoes not support the mmxscript set. I use the vs2005ml.exe version 8.00.50727, And the masm32 version is version 6.14. It is better to replace it... it is also an upgrade. Haha !!
; **************************************** ***********
; Hexadecimal string to DWORD or qword (MMX)
; Author bitrake
; Analysed by G-spider
; Ml/C/coff Hex. ASM
; Link/subsystem: Windows Hex. OBJ
; **************************************** ***********
. 586
. MMX
. Model flat, stdcall
Option Casemap: None
Include windows. inc
Include user32.inc
Include kernel32.inc
Includelib user32.lib
Includelib kernel32.lib
; **************************************** *******
; This macro repeat the data into 8 bytes
; For example: mxc (<30>); byte-level repetition
; Equivalent to the number of seconds 30 30 30 30 30 30 30 30 30 h
; For example: mxc (<0f00>); Word-level repetition
; Equivalent to the number of 0f00 0f00 0f00 0f00h
For example, mxc (<0f000000>); dual-word repetition
; Equivalent to the number of 0f000000 0f000000h
Mxc macro VAL: req
Local W, Y, Z
Z sizestr <& Val>
; Attempt to compact data
While (Z lt 17) and (z GT 2)
Z = z/2
Ifdif @ substr (<& Val>, 1, Z), @ substr (<& Val>, 1 + Z, Z)
Z = z + Z + 16
Endif
Endm
If z gt 16
Z = z-16
Endif
W textequ @ substr (<& Val>, 1, Z)
; Figure out global name for constant
Y catstr <__ MMX _>, W
If (opattr (y) eq 0; Not Defined
Const $ MMX segment
Y label qword
W catstr <0>, W, If z eq 16
DQ W
Elseif z eq 8
Dd W, W
Elseif z eq 4
Dw w, W
Elseif z eq 2
Db w, W
Endif
Const $ MMX ends
Endif
Exitm y
Endm
; **************************************** ***********
. Data
Sztitlesave dB 'Good luck ', 0
FMT dB '% x', 0
. Data?
Buf dB 16 DUP (?)
. Code
; Fast string to DWORD functions (MMX Instruction Set)
Strhex2bin proc
_ Const segment
Lpstring DB "89 abcdef"
; // "89 abcdef" => 38 H | 39 h | 61 H | 42 h | 63 H | 44 h | 65 h | 46 h
_ Const ends
Movq mm0, qword PTR [lpstring]
; Mm0 = 46 65 44 63 42 61 39 38 H <= Note that the data is retrieved in the lower upper-level mode.
Psubusb mm0, mxc (<30>); "0" = 0
; Mxc (<30>) = 30 30 30 30 30 30 30 30 h
; Psubusb XMM, XMM/m128
The source memory and the destination register are aligned byte with the unsigned saturation subtraction (destination minus source). The memory variable must be aligned with the memory 16 bytes.
; Mm0 = 16 35 14 33 12 31 09 08 h
Movq MM1, mm0
; Movq XMM, XMM/M64
The low 64-bit content of the source memory is sent to the low 64-bit destination register, and the high 64-bit is cleared.
; MM1 = 16 35 14 33 12 31 09 08 h
Pcmpgtb MM1, mxc (<09>); letter?
; Mxc (<09>) = 09 09 09 09 09 09 09 h
; Pcmpgtb mm, mm/M64
; Compare the source register with the target register by byte (signed complement,
When the corresponding byte of the destination register is greater than that of the source register, the corresponding byte of the destination register is set to 0ffh; otherwise, the value is 00 H.
; MM1 = 0 FFFF ffffff 0000 h
Pand MM1, mxc (<07>)
; Pand XMM, XMM/m128
128 binary bits in the source memory and 128 binary bits in the destination register. The result is sent to the destination register. The memory variables must be aligned with 16 bytes in the memory.
; Mm0 = 16 35 14 33 12 31 09 08 h
; MM1 = 07 07 07 07 07 00 00 h
Psubusb mm0, MM1; fix letters
; Mm0 = 0f 2E 0d 2C 0b 2a 09 08 h
Movq MM1, mm0
; MM1 = 0f 2E 0d 2C 0b 2a 09 08 h
Pand mm0, mxc (<0f00>)
; Mxc (<0f00>) = 0f00 0f00 0f00 0f00h
; Mm0 = 0f00 0d00 0b00 0900 H
Pand MM1, mxc (<000f>)
; Mxc (<000f>) = 000f 000f 000f 000fh
; MM1 = 000e 000c 000a 0008 H
Psrscsi mm0, 8
Assembly command: psrscsi
Function Description: shifts the integer in M1 to the right of the count bit until it is 0.
; Mm0 = 000f 000d 000b 0009 H
; MM1 = 000e 000c 000a 0008 H
Packuswb MM1, MM1
Compress the destination Register into byte unsigned characters by the number of characters into the destination register, which is 32 characters lower.
The source register is compressed to the byte unsigned number by the number of characters into the high 32-bit destination register
During compression, the negative number becomes 00 h, and the positive number greater than 255 becomes 0ffh.
; MM1 = 0e 0C 0a 08 0e 0C 0a 08 h
; Mm0 = 000f 000d 000b 0009 H
Packuswb mm0, mm0
; Mm0 = 0f 0d 0b 09 0f 0d 0b 09 h
; MM1 = 0e 0C 0a 08 0e 0C 0a 08 h
Psllq MM1, 4
; Shifts the integer in M1 to the left of the count bit until it becomes 0.
; MM1 = E0 C0 A0 80 E0 C0 A0 80 h
; Mm0 = 0f 0d 0b 09 0f 0d 0b 09 h
Por mm0, MM1
; Por mm, mm/M64
; 64-bit 'or' operation, and the result is put into the destination register.
; Mm0 = EF ed AB 89 ef cd AB 89 h
Movd eax, mm0
; Eax = ef cd AB 89 h
Bswap eax
; Eax = 89 AB CD EFH
RET
Strhex2bin endp
Start:
Invoke strhex2bin
Invoke wsprintf, offset Buf, offset FMT, eax
Invoke MessageBox, null, offset Buf, ADDR sztitlesave, 0
RET
End start
In an algorithm Forum {
Tagshow (Event)
} "> The Forum found that someone needed a hexadecimal string to convert the four-character (64-bit) or double-character (32-bit) data, so we expanded the above:
(When thinking about using the SSE instruction set, I found that the biggest difficulty was that I could not directly read 16 bytes of data. I tried oword as though not supported or could not achieve the expected results ).
; **************************************** ***********
; Hexadecimal string to DWORD or qword (MMX)
; Author bitrake http://madwizard.org/programming/snippets? Id = 43
; Updated by G-spider
; Ml/C/coff Hex. ASM
; Link/subsystem: Windows Hex. OBJ
; **************************************** ***********
. 586
. MMX
. Model flat, stdcall
Option Casemap: None
Include windows. inc
Include user32.inc
Include kernel32.inc
Includelib user32.lib
Includelib kernel32.lib
; **************************************** ***********
. Data
Sztitlesave dB 'Good luck ', 0
FMT dB '% x % x', 0
Align 16
_ 0 fill dB 16 DUP (0); need! When _ stringlong <16
_ Lpstring DB "89abcdef12acdeff", 0; test1 <=== note! Have zero end
; _ Lpstring DB "89abcdef12", 0; Test2
; _ Lpstring DB "89 ABCDE", 0; test3
; _ Lpstring DB "89abcdef12345678ad", 0; test4
_ Stringlong dd $-_ lpString-1
; _ Lpstring DB "89abcdef12345678"; <=== note! No zero end
; _ Stringlong dd $-_ lpstring
Align 16; <= note!
_ 3hex qword 3030303030303030 H
_ 9hex qword 0909090909090909 H
_ 7hex qword 0707070707070707 H
_ F0hex qword 0f000f000f000f00h
_ 0 fhex qword 000f000f000f000fh
. Data?
Buf dB 16 DUP (?)
. Code
Strhex2bin proc lpstring: DWORD
MoV eax, lpstring
Movq mm0, qword PTR [eax]
Psubusb mm0, _ 3hex; "0" = 0
Movq MM1, mm0
Pcmpgtb MM1, _ 9hex; letter?
Pand MM1, _ 7hex
Psubusb mm0, MM1; fix letters
Movq MM1, mm0
Pand mm0, _ f0hex
Pand MM1, _ 0 fhex
Psrscsi mm0, 8
Packuswb MM1, MM1
Packuswb mm0, mm0
Psllq MM1, 4
Por mm0, MM1
Movd eax, mm0
Bswap eax
RET
Strhex2bin endp
Strhex2qword proc lpstring, stringlong
MoV EBX, lpstring
Add EBX, stringlong
Sub EBX, 16
Push EBX
Invoke strhex2bin, EBX
MoV edX, eax; edX = quadword. hidword
Pop EBX
Add EBX, 8
Invoke strhex2bin, EBX; eax = quadword. lodword
RET
Strhex2qword endp
Start:
Invoke strhex2qword, offset _ lpstring, _ stringlong
Invoke wsprintf, offset Buf, offset FMT, EDX, eax
Invoke MessageBox, null, offset Buf, ADDR sztitlesave, 0
RET
End start