Win32 Assembly
Figura 1 - Direttive per l'assembler |
---|
.386 ; set di istruzioni a 32 bit .MODEL FLAT, STDCALL ; memory model & calling conventions OPTION CASEMAP: NONE ; case-sensitive on symbols INCLUDE ..\include\windows.inc ; include file principale di Win32 INCLUDE ..\include\user32.inc ; interfaccia per USER32.LIB INCLUDE ..\include\kernel32.inc ; interfaccia per KERNEL32.LIB INCLUDELIB ..\lib\user32.lib ; libreria servizi GUI INCLUDELIB ..\lib\kernel32.lib ; libreria servizi kernel |
.386
,.MODEL FLAT, STDCALL
,mov ax, [ebx]
.OPTION CASEMAP: NONE
,include ..\include\windows.inc
,INCLUDELIB
.Figura 2 - Segmento dati inizializzati |
---|
_DATA SEGMENT DWORD PUBLIC USE32 'DATA' _DATA ENDS |
varWord1 dw 12800
,.MODEL
usata per definire il modello
di memoria del nostro programma, possiamo anche servirci delle direttive semplificate per la
creazione dei segmenti di programma; nel caso del segmento dati inizializzati, possiamo sostituire
tutto cio' che si vede in Figura 2 con la direttiva semplificata .DATA
.
varDword1 dd ?
.Figura 3 - Segmento dati non inizializzati |
---|
_BSS SEGMENT DWORD PUBLIC USE32 'BSS' _BSS ENDS |
.DATA?
.
printf("Premere un tasto per continuare");
Figura 4 - Segmento dati costanti |
---|
_CONST SEGMENT DWORD PUBLIC USE32 'CONST' _CONST ENDS |
.CONST
.
Figura 5 - Definition File |
---|
NAME Win16App DESCRIPTION 'Applicazione per Win16' EXETYPE WINDOWS STUB 'WINSTUB.EXE' CODE PRELOAD MOVEABLE DISCARDABLE DATA PRELOAD MOVEABLE MULTIPLE HEAPSIZE 1024 STACKSIZE 8192 |
This program requires Microsoft Windows
Figura 6 - Segmento di codice |
---|
_TEXT SEGMENT DWORD PUBLIC USE32 'CODE' start: ; entry point del programma ; -------------- inizio blocco istruzioni -------------- ; --------------- fine blocco istruzioni --------------- push dword ptr 0 ; exit code = 0 call ExitProcess ; termina il programma _TEXT ENDS |
void ExitProcess(UINT uExitCode);
UINT TYPEDEF DWORD
,UINT equ DD
;push dword ptr 0
.call ExitProcess
;ret (4)
(1 DWORD = 4 BYTE).add esp, 4
,pop eax
..MODEL
, possiamo evitare tutto
questo lavoro sfruttando le istruzioni avanzate di TASM e MASM; nel caso di
TASM possiamo scrivere:call ExitProcess, 0
,invoke ExitProcess, 0
..MODEL
per sapere come si deve comportare; tutto il lavoro
svolto dall'assembler puo' essere analizzato attraverso il Listing File.
Figura 7 - Definizione di dati nel blocco codice |
---|
_TEXT SEGMENT DWORD PUBLIC USE32 'CODE' start: ; entry point del programma jmp short start_code: ; salta le definizioni dei dati varCode1 dw 13500 varCode2 dd 400000 varCode3 dw 3FA0h start_code: ; -------------- inizio blocco istruzioni -------------- ; --------------- fine blocco istruzioni --------------- push 0 ; exit code = 0 call ExitProcess ; termina il programma _TEXT ENDS |
.MODEL
, possiamo servirci delle direttive
semplificate per i segmenti di programma; nel caso di Figura 6 o di Figura 7, l'inizio del
segmento di codice puo' essere indicato attraverso la direttiva semplificata
.CODE
.
DGROUP GROUP _DATA, _CONST, _STACK, _BSS
Figura 8 - Template di un programma Assembly per Win32 |
---|
call ExitProcess, 0
;invoke ExitProcess, 0
.MODEL
). Le direttive avanzate
CALL e INVOKE lavorando in combinazione con i prototipi delle procedure,
sono in grado di rilevare eventuali errori che possiamo commettere nel passaggio degli
argomenti alle procedure stesse; l'unico (grave) problema e' dato dal fatto che MASM
non supporta la direttiva avanzata CALL e TASM ricambia il favore non
supportando la direttiva avanzata INVOKE. Per i piccoli programmi, questo problema
puo' essere facilmente superato con l'utilizzo delle direttive condizionali; nel caso del
template di Figura 8, nel blocco delle direttive per l'assembler possiamo inserire la
dichiarazione:TASM = 1
.IF TASM call ExitProcess, 0 ELSE invoke ExitProcess, 0 ENDIF |
invoke equ call
.
Figura 9 - Template di un programma Assembly per Win32 |
---|
mov dx, [eax + edi + 120500]
; int copiaStringa(char *strTo, char *strFrom); copiaStringa proc strTo equ [ebp+8] ; parametro strTo strFrom equ [ebp+12] ; parametro strFrom strCount equ [ebp-4] ; var. locale strCount push ebp ; preserva ebp mov ebp, esp ; ss:ebp = ss:esp sub esp, 4 ; spazio per strCount mov dword ptr strCount, -1 ; strCount = -1 mov esi, strFrom ; esi = sorgente mov edi, strTo ; edi = destinazione strCopyLoop: mov al, [esi] ; copia da sorgente mov [edi], al ; a destinazione inc esi ; incremento puntatore inc edi ; incremento puntatore inc dword ptr strCount ; incremento contatore test al, al ; fine stringa C ? jnz strCopyLoop ; controllo loop mov eax, strCount ; valore di ritorno mov esp, ebp ; ripristina esp pop ebp ; ripristina ebp ret 8 ; pulizia stack e return copiaStringa endp |
push offset strSource push offset strDest call copiaStringa |
.386 ; set di istruzioni a 32 bit .MODEL FLAT, STDCALL ; memory model & calling conventions |
copiaStringa PROTO :DWORD, :DWORD
; int copiaStringa(char *strTo, char *strFrom); copiaStringa proc strTo :DWORD, strFrom :DWORD LOCAL strCount :DWORD ; contatore mov dword ptr strCount, -1 ; strCount = -1 mov esi, strFrom ; esi = sorgente mov edi, strTo ; edi = destinazione strCopyLoop: mov al, [esi] ; copia da sorgente mov [edi], al ; a destinazione inc esi ; incremento puntatore inc edi ; incremento puntatore inc dword ptr strCount ; incremento contatore test al, al ; fine stringa C ? jnz strCopyLoop ; controllo loop mov eax, strCount ; valore di ritorno ret ; return copiaStringa endp |
call copiaStringa, strDest, strSrc
invoke copiaStringa, strDest, strSrc