Zoom Icon

Assembly MMX

From UIC

Assembly MMX

Contents


Assembly MMX
Author: Pn
Email: Pnmail.png
Website: No Site
Date: 03/11/2007 (dd/mm/yyyy)
Level: Some skills are required
Language: Italian Flag Italian.gif
Comments: I'm back!!!



Link e Riferimenti

Manuali Intel
MASM Programmer's Guide
Masm 9


Essay

Col Pentium II sono state introdotte delle estensioni all'architettura del processore: MMX e SSE, che permettono di effettuare le operazioni SIMD (single-instruction multiple-data).
Ognuna di queste estensioni fornisce un gruppo di istruzioni, che operano tramite i packed integer ed i packed floating point, usando i registri MMX (a 64bit) o quelli XMM (a 128bit).


SIMD Execution Model

Il modello SIMD velocizza di molto le performance del software, permettendo di operare su diversi dati in parallelo con una sola istruzione.

None


Packed Data Types

I Packed Data Type sono di due tip: 64 e 128 bit, e sono la versione digitale dei vettori.

64bit Packed Data Types

I 64-bit packed SIMD data types sono stati introdotti con la tecnologia MMX. I tipi fondamentali sono: packed byte, packed word, packed dword e possono contenere soltanto valori integer.

None

128bit Packed Data Types

I 128-bit packed SIMD data types sono stati introdotti con la tecnologia XMM. I tipi fondamentali sono: packed byte, packed word, packed dword e packed qword. Questo tipo di packed possono contenere valori integer o a virgola mobile(floating point)

None


MMX Technology

La tecnologia MMX ha introdotto il concetto di operazioni SIMD , i packed data types, e poi l' ambiente MMX .

MMX registers

L'ambiente MMX implementa otto registri da 64bit, utilizzati per effettuare operazioni sui packed data.
I registri MMX sono "contenuti" nei registri della FPU, in effetti, si agisce fisicamente sui i registri della FPU, l'immagine chiarisce meglio questo concetto.

None

E' possibile accedere ai registri con modalità a 32bit ed a 64bit.
In entrambe le modalità d'accesso alla memoria, i registri svolgono le seguenti operazioni:

  • Accesso alla memoria secondo la codifica little indian
  • Trasferimento dati da un registro MMX all'altro
  • Istruzioni per unpack/pack


Saturazione e wraparound modes

Quando si esegue un' operazione aritmetica, essa può risultare fuori range, es: sommando due word, si può ottenere un overflow se il risultato è maggiore di 16bit.
Per ovviare a ciò MMX implementa due tecniche:

  • Wraparound: con questa tecnica il risultato è truccato: il carry o l'overflow bit è ignorato e solo l'ultimo bit significativo del risultato è ritornato alla destinazione.
  • Signed and Unsegned Saturation: il risultato è limitato alla grandezza del packed data operante: se l'addizione tra due word packed è maggiore di 16bit, il risultato è saturato(per i signed) a 7FFF, se avviene un positive overflow, o 8000, se avviene un negative overflow o è un'operazione unsigned.

MMX instructions

Ecco a voi una tabella contenente le istruzioni supportate dalla tecnologia MMX

None

  • EMMS: quest'istruzione svuota lo stato dell'ambiente MMX settando a 11B il FPU tag word. Quest'istruzione deve essere inserita alla fine di ogni blocco di codice che utilizzi le istruzioni MMX, prima di eseguire codice per la FPU.
  • Arithmetic Instructions:
    • PADDB/PADDW/PADDD: sono le istruzione per l'addizione dei packed data considerandoli come vettori di byte/word/dword
    • PSUBB/PSUBW/PSUBD: solo le istruzioni per la sottrazione dei packed data.
    • PADDUSB/PADDSW: aggiunge i packed data, considerati come numeri con segno(byte e word), usando la signed saturation.
    • PSUBSB/PSUBSW: come sopra, solo che queste istruzioni vengono usate per effettuare la sottrazione
    • PADDUSB/PADDUSW: aggiunge i packed data, considerandoli come numeri senza segno(byte e word), usando l'unsigned saturation.
    • PSUBSUB/PSUBUSW: come sopra ma utilizzati per la sottrazione.
    • PMULHW/PMULHUW: moltiplica due packed signed/unsigned word e salva i 16bit più alti, dal bit 31 al 16, dei 32bit risultanti della moltiplicazione.
    • PMADDWD: Moltiplica ed aggiunge due packed word integer: per farla breve:
      None
  • Comparison Instructions:
    • PCMPEQB: Compare packed bytes for equal
    • PCMPEQW: Compare packed words for equal
    • PCMPEQD: Compare packed doublewords for equal
    • PCMPGTB: Compare packed signed byte integers for greater than
    • PCMPGTW: Compare packed signed word integers for greater than
    • PCMPGTD: Compare packed signed doubleword integers for greater than
  • Logical Instructions:
    • PAND: bitwise logical AND
    • PANDS: bitwise logical AND NOT
    • POR: bitwise logical OR
    • PXOR: bitwise logical XOR
  • Shift and Rotate Instructions:
    • PSLLW: shift packed words left logical
    • PSLLD: shift packed dwords left logical
    • PSLLQ: shift packed qwords left logical
    • PSRLW: shift packed words right logical
    • PSRLD: shift packed dwords right logical
    • PSRLQ: shift packed qwords right logical
    • PSRAW: shift packed words right arithmetic
    • PSRAD: shift packed dwords right arithmetic
  • Coversion istructions: Le istruzioni PACKSSWB (pack word in byte con signed saturation), PACKSSDW (pack dword in word con signed saturation) e PACKUSWB (pack word in byte con l'unsigned saturation): sono delle istruzioni di conversione. Per comprendere meglio questo tipo d' istruzioni guardate quest'immagine:
None
  • Unpack istructions: Le istruzioni di unpack sono di due tipi: quelle che operano sui High Data e quelli sui Low Data:
    • High Data: estraggono ed intervallano gli high-order data element (prende dalla parte superiore del registro i byte/word/dword/qword) dalla sorgente e dal destinatario nel registro del destinatario.
      None
    • Low data: come sopra, solo che operano sui low data (la parte inferiore del registro)
None

Per approfondire le altre istruzioni vi rimando ai manuali intel volume 1 e 2.

Example

Ora mostro un semplice programma che effettua delle operazioni sui vettori (secondo voi i packed data cosa sono ;).

Codice per MASM/x86

.686
.MMX
.model flat, stdcall

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

.data
        r1 dw 0,0,-2,712 ;array di word
        r2 dw 0,2,4,-10  
        r3 dw 0,2,4,5
       
        Titolo db "ciao",0
        Testo1 db "minore",0   
        Testo2 db "maggiore",0

.code
        Main:

        ;verifico che il processore supporti MMX
        mov eax, 1
        cpuid
        test edx, 0800000h
        jz exit

        movq MM0, qword ptr [r1] ;copio tre qword nei registri MMX
        movq mm1, qword ptr[r2]
        movq mm2, qword ptr[r3]; rappresentato come 0005 0004 0002 0000, secondo codifica little indian
        paddsb mm0, mm1  ;addiziono due vettori
        psubsb mm2,mm0   ;sottraggo due vettori
        movq qword ptr[r1],mm0
        pcmpeqb mm0, mm1  ;faccio una comparazione
        jb minor
        invoke MessageBox, NULL, OFFSET Testo2,OFFSET  Titolo, 0
        jmp exit
minor:
        invoke MessageBox, NULL, OFFSET  Testo1, OFFSET Titolo, 0      
exit:
        emms  ;è d'obbligo
        invoke ExitProcess, NULL
       
       
        end Main

Codice per ml64/x64

extrn MessageBoxA : proc
extrn ExitProcess : proc

.data
        r1 dw 0,0,-2,712 ;array di word
        r2 dw 0,2,4,-10  
        r3 dw 0,2,4,-5
       
        Titolo db "ciao",0
        Testo1 db "minore",0  
        Testo2 db "maggiore",0

.code
        Main proc
        sub rsp, 28h
       
        ;verifico che il processore supporti MMX
        mov eax, 1
        cpuid
        test edx, 0800000h
        jz exit

        movq MM0, qword ptr [r1] ;copio tre qword nei registri MMX
        movq mm1, qword ptr[r2]
        movq mm2, qword ptr[r3]
        paddsb mm0, mm1  ;addiziono due vettori
        psubsb mm2,mm0   ;sottraggo due vettori
        movq qword ptr[r1],mm0
        pcmpeqb mm0, mm1  ;faccio una comparazione
        jb minor
        xor r9, r9
        lea r8, Titolo
        lea rdx, Testo2
        xor rcx, rcx
        call MessageBoxA
        jmp exit
minor:
        xor r9, r9
        lea r8, Titolo
        lea rdx, Testo1
        xor rcx, rcx
        call MessageBoxA    
exit:
        emms  ; e' d'obbligo
        xor rcx, rcx
        call ExitProcess
       
        Main endp
end

SSE Technology

Vi rimando all'ottimo tutorial di MrCode =)



Note Finali

Ora voglio vedere un sacco di crackme che implementino i sistemi lineari =)

Pn =)


Disclaimer

I documenti qui pubblicati sono da considerarsi pubblici e liberamente distribuibili, a patto che se ne citi la fonte di provenienza. Tutti i documenti presenti su queste pagine sono stati scritti esclusivamente a scopo di ricerca, nessuna di queste analisi è stata fatta per fini commerciali, o dietro alcun tipo di compenso. I documenti pubblicati presentano delle analisi puramente teoriche della struttura di un programma, in nessun caso il software è stato realmente disassemblato o modificato; ogni corrispondenza presente tra i documenti pubblicati e le istruzioni del software oggetto dell'analisi, è da ritenersi puramente casuale. Tutti i documenti vengono inviati in forma anonima ed automaticamente pubblicati, i diritti di tali opere appartengono esclusivamente al firmatario del documento (se presente), in nessun caso il gestore di questo sito, o del server su cui risiede, può essere ritenuto responsabile dei contenuti qui presenti, oltretutto il gestore del sito non è in grado di risalire all'identità del mittente dei documenti. Tutti i documenti ed i file di questo sito non presentano alcun tipo di garanzia, pertanto ne è sconsigliata a tutti la lettura o l'esecuzione, lo staff non si assume alcuna responsabilità per quanto riguarda l'uso improprio di tali documenti e/o file, è doveroso aggiungere che ogni riferimento a fatti cose o persone è da considerarsi PURAMENTE casuale. Tutti coloro che potrebbero ritenersi moralmente offesi dai contenuti di queste pagine, sono tenuti ad uscire immediatamente da questo sito.

Vogliamo inoltre ricordare che il Reverse Engineering è uno strumento tecnologico di grande potenza ed importanza, senza di esso non sarebbe possibile creare antivirus, scoprire funzioni malevole e non dichiarate all'interno di un programma di pubblico utilizzo. Non sarebbe possibile scoprire, in assenza di un sistema sicuro per il controllo dell'integrità, se il "tal" programma è realmente quello che l'utente ha scelto di installare ed eseguire, né sarebbe possibile continuare lo sviluppo di quei programmi (o l'utilizzo di quelle periferiche) ritenuti obsoleti e non più supportati dalle fonti ufficiali.