[分析]快速字串轉DWORD型的函數(MMX指令集)

來源:互聯網
上載者:User

請用帶文法高亮的編輯器查看,可讀性將大大增強,若邊查MMX指令(我已經注釋了),再用OD跟蹤mm0, mm1的值(分別對應st(0)和st(1)的低64位),可加深理解!!
可能低版本的ml.exe不支援MMX指令集,我用的是VS2005的ml.exe 版本是8.00.50727  而masm32中的是6.14 版的,替換一下更好...也算是升級了,哈哈!!

;***************************************************
;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

;***********************************************
;此宏將資料重複成8位元組
;如:mxc(<30>) ;位元組級重複
;等價於立即數30 30 30 30 30 30 30 30h
;如: mxc(<0f00>) ;字級重複
;等價於立即數0f00 0f00 0f00 0f00h
;如: mxc(<0f000000>) ;雙字級重複
;等價於立即數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,<h>
            IF z EQ 16
                dq w
            ELSEIF z EQ 8
                dd w,w
            ELSEIF z EQ 4
                dw w,w,w,w
            ELSEIF z EQ 2
                db w,w,w,w,w,w,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
;快速字串轉DWORD型的函數(MMX指令集)
StrHex2bin PROC
    _CONST SEGMENT
        lpString db "89aBcDeF"
        ;//"89aBcDeF"=>38h | 39h || 61h | 42h ||| 63h | 44h || 65h | 46h 
    _CONST ENDS
    movq mm0,QWORD PTR [lpString]
    ;mm0=46 65 44 63 42 61 39 38 h  <==注意取資料為低上位方式
    
    psubusb  mm0,mxc(<30>) ; "0" = 0
    ;mxc(<30>)=30 30 30 30 30 30 30 30 h 
    ;psubusb XMM,XMM/m128
    ;源儲存空間與目的寄存器按位元組對齊無符號飽和相減(目的減去源),記憶體變數必須對齊記憶體16位元組.
    ;mm0=16 35 14 33 12 31 09 08 h
    
    movq mm1,mm0
    ;movq XMM,XMM/m64
    ;把源儲存空間低64位內容送入目的寄存器的低64位,高64位清零.
    ;mm1=16 35 14 33 12 31 09 08 h 
    
    pcmpgtb mm1,mxc(<09>) ; letter?
    ;mxc(<09>)=09 09 09 09 09 09 09 09h
    ;pcmpgtb MM,MM/m64
    ;源寄存器與目的寄存器按位元組(有符號補碼)比較,
    ;當目的寄存器對應位元組大於源寄存器就置目的寄存器對應位元組為0ffh,否則為00h
    ;mm1=0 ffff ffff ffff 0000h
    pand mm1,mxc(<07>)
    ;pand XMM,XMM/m128
    ;源儲存空間128個二進位位'與'目的寄存器128個二進位位,結果送入目的寄存器,記憶體變數必須對齊記憶體16位元組.
    ;mm0=16 35 14 33 12 31 09 08h
    ;mm1=07 07 07 07 07 07 00 00h
    
    psubusb mm0,mm1 ; fix letters
    ;mm0=0f 2e 0d 2c 0b 2a 09 08h

    movq mm1,mm0         
    ;mm1=0f 2e 0d 2c 0b 2a 09 08h    
    pand mm0,mxc(<0F00>) 
    ;mxc(<0F00>)=0f00 0f00 0f00 0f00h
    ;mm0=0f00 0d00 0b00 0900h
    pand mm1,mxc(<000F>) 
    ;mxc(<000F>)=000f 000f 000f 000fh
    ;mm1=000e 000c 000a 0008h
    psrlq mm0,8         
    ;彙編指令:PSRLQ
    ;功能說明:將m1中的整數右移count位,直到變為0才停止。
    ;mm0=000f 000d 000b 0009h
    
    ;mm1=000e 000c 000a 0008h
    packuswb mm1,mm1     
    ;把目的寄存器按字有符號數壓縮為位元組無符號數放入目的寄存器低32位
    ;把源寄存器按字有符號數壓縮為位元組無符號數放入目的寄存器高32位
    ;壓縮時負數變為00h,大於255的正數變為0ffh.
    ;mm1=0e 0c 0a 08  0e 0c 0a 08 h

    ;mm0=000f 000d 000b 0009h
    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         
    ;將m1中的整數左移count位,直到變為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個位'或'操作,結果放入目的寄存器.
    ;mm0=ef ed ab 89  ef cd ab 89 h
    
    movd eax,mm0        
    ;eax=ef cd ab 89h 
    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

 

在某個演算法論壇{
tagshow(event)
}">版塊發現有人需要十六進位串轉四字(64位)或雙字型(32位)資料,所以在上面的基礎上擴充了一下:
(當初想著考慮用SSE指令集,發現一個最大的困難是無法直接讀取16位元組資料,嘗試了OWORD好像不支援或得不到預期的效果)。

;***************************************************
;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 
_0fill          db  16  dup(0)            ;Need! When _StringLong<16
_lpString       db "89aBcDeF12aCdEfF",0   ;Test1 <====note! Have Zero End
;_lpString      db "89aBcDeF12",0         ;Test2
;_lpString      db "89aBcDe",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   3030303030303030h
_9Hex           qword   0909090909090909h
_7Hex           qword   0707070707070707h 
_f0Hex          qword   0f000f000f000f00h  
_0fHex          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,_0fHex
        psrlq       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

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.