eWorld ReSearch - Assembler Tutorial
eWorld Network ReSearch
Last update: 12/1999
by Alessandro Polo
Assembler Tutorial
Descrizione
Questo documente spiega brevemente e sommariamente la basi
dell'Assembler x86.
Puo essere un primo approccio alla programmazione di primo
livello.
Sistemi binario,
decimale,
esadecimale
Noi siamo abituati a lavorare con il sistema decimale, ma i
computer a livello hardware utilizzano il sistema binario
(combinazioni di 0 e 1), il pc usa ovviamente anche il sistema
esadecimale.
Un cracker o un programmatore di Assembler deve conoscere
tutti i sistemi elencati e sapere come convertire cifre.
Il sistema più vicino a noi è quello decimale, quindi useremo
quello per rendere gli altri sistemi più "amichevoli", il sistema
binario utilizza infatti le cifre 0 e 1, quello il base 8 riciclerà le cifre
da 0 a 7.
Per il sistema esadecimale ci sono 16 cifre e quindi siamo costretti
a ricorrere alle letter dell'alfabeto:
Esadecimale:0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 .
Convertito: 0 1 2 3 4 5 6 7 8 9 A B C D E F .
Quindi mentre il sistema decimale è "matematicamente
incompatibile" col sistema esadecimale, il sistema binario è molto
vicino ad entrambi, esso infatti lavora in base due e 2*2*2*2=16
(base esadecimale).
●
Conversione Binaria a Decimale
Prendiamo ad esempio 11011b in complemento a due, a
che numero decimale corrisponde?
numero binario: 1
1
2^4 2^3
potenze di 2:
+8
formato decimale:16
sommando..
risultato:
= 27
●
0
2^2
+0
Conversione Binaria a Esadecimale
1
2^1
+2
1
2^0
+1
eWorld ReSearch - Assembler Tutorial
Utilizzando lo stesso esempio calcoliamo il corrispondente
esadecimale.
(dividiamo in gruppi di quattro da dx verso sx)
numero binario: 1
2^4
potenze di 2:
formato decimale:16
1
2^3
+8
in Hex
8+2
+1=11
= B
1
risultato:
●
0
2^2
+0
1
2^1
+2
1
2^0
+1
= 1B
Conversione Decimale a Binaria
Come avrete tutti studiato parecchi anni fa per convertire
un valore decimale in uno binario si gioca sulle divisioni e
sul rimanente. DIV è il risultato della divisione mentre MOD
è il resto.
Così se scriverò 15 MOD 2 il risultato sarà DIV=7, MOD=1
(il simbolo che identifica MOD è %).
Praticamente per trasformare un numero decimale in uno
binario è sufficiente continuare a dividere per due
componendo la cifra binaria da destra verso sinistra:
15/2 =7 +1 BIN -> 1
7 /2 =3 +1 BIN -> 11
3 /2 =1 +1 BIN -> 111
1 /2 =0 +1 BIN -> 1111
Hex
0
1
2
3
4
5
6
7
8
9
A
B
C
D
Bin
0000
0001
0010
0011
0100
0101
0110
0111
1000
1001
1010
1011
1100
1101
eWorld ReSearch - Assembler Tutorial
E
F
1110
1111
Quindi ad esempio 1101 1011 0111 0101 0011 corrisponde a D B
7 5 3.
●
Operazioni & Logica
Per distinguere la base di ogni cifra l'Assembler aggiunge
l'iniziale del sistema al termine del numero
Suffisso Sistema
b
Binario
o
d
h
Ottale
Decimale
Esadecimale
Per scrivere il numero 7 in base due in 8 bit di
memoria: 00000111.
Se vogliamo rappresentare il numero -7 la cosa è più
complessa:
00000111
invertiamo i bit:
11111000
aggiungiamo 1 al numero 11111000 + 1 =
11111001 --> -7
Infatti:
(111 + 11111001 = 0 <->
7 - 7 = 0)
Il valore 1 corrisponde a vero mentre 0 corrisponde a
falso, entriamo nell'affascinante mondo della logica
(sezione della matematica che studia i predicati).
Le operazioni fondamentali (porte logiche) sono
AND, OR, NOT, XOR.
Ecco una tabella riassuntiva dei risutati:
c = a AND b
a
0
0
1
1
b
0
1
0
1
c
0
0
0
1
c = a OR b
a
0
0
1
1
b
0
1
0
1
c
0
1
1
1
eWorld ReSearch - Assembler Tutorial
c = NOT a
c = a XOR b
a
0
1
c
1
0
(NOT funziona con una
sola variabile)
Unità di misura
della memoria
ab c
00 0
01 1
10 1
11 0
E' necessario introdurre ancora altri concetti prima di passare alla
vera e propria programmazione, un concetto che non sarà
senz'altro nuovo è quello de Bit, Byte, Word..
Un Bit è una cifra binaria: 0 oppure 1.
Un Byte è una concatenazione di 8 Bit quindi 10010010, un byte
può rappresentare un qualsiasi numero tra 0 e 2^8-1 (=255) o un
qualsiasi esadecimale da 0 a FF.
Una Word è l'unione di 2 byte, quindi sono in totale 16bit di
memoria, i numeri arrivano a 65535, in Esadecimale fino a FFFF.
Una Double Word è 2 Word ossia 4 byte, da 0 a 4294967295 e in
esa da 0 a FFFFFFFF.
Poi: un Kilobyte è 1024 Byte, un Mega 1024 Kilobyte, Un Gigabyte
1024 Megabyte.
I Registri
I registri sono delle locazioni di memoria dove il nostro
programma può salvare dati, puntatori.. I Registri in questione
sono AX, BX, CX, DX.
●
●
●
●
AX - Registro a 16bit (divisibile in AH e AL da 8bit
ciascuno), è detto "accumulatore" poichè è spesso usato
per memorizzare calcoli matematici.
BX - Registro a 16bit (divisibile in BH e BL da 8bit
ciascuno), usato spesso per memorizzare OFFSET.
CX - Registro a 16bit (divisibile in CH e CL da 8bit
ciascuno), impiegato nella maggior parte dei casi come
contatore di cicli.
DX - Registro a 16bit (divisibile in DH e DL da 8bit
ciascuno), usato per memorizzare grosse cifre matematiche
e come puntatore nell'I/O.
eWorld ReSearch - Assembler Tutorial
●
●
●
●
●
BP - Registro a 16bit (Base Pointer), Puntatore di base dello
stack.
CS - (Code Segment), Contiene l'istruzione di programma
da eseguire.
DS - (Data Segment), Contiene dati dell'applicazione.
ES - (Extra Segment), Registro aggiuntivo.
SS - (Stack Segment), Contiene lo Stack.
Dalle architetture del 386 sono stati aggiunti i registri 32bit: EAX,
EBX, ECX, EDX, ESI, EDI, EBP.
Ci sono altri due registri (spesso utili nel cracking) creati
appositamente per la manipolazione delle stringhe:
●
●
Il Registro FLAG
DI - Registro di Destinazione
SI - Registro di Partenza
Questo registro viene utilizzato come memoria per l'esecuzione
delle istruzioni, ad esempio se si esegue una sottrazzione che da
come risultato zero, il FLAG verrà impostato a zero, quindi il 6° bit
sarà 1.
Bit
0
1
2
3
4
5
6
7
8
9
A
B
C
D
E
F
10
11
Descrizione
CF Carry Flag
1
PF Parity Flag
0
AF Auxiliary Flag
0
ZF Zero Flag
SF Sign Flag
TF Trap Flag (Single Step)
IF Interrupt Flag
DF Direction Flag
OF Overflow flag
0
IOPL I/O Privil. Level(286+ only)
NT Nested Task Flag (286+ only)
0
RF Resume Flag (386+ only)
VM Virtual Mode Flag (386+ only)
eWorld ReSearch - Assembler Tutorial
Segmenti e OffSets Le vecchie CPU dovevano gestire solo 1 mega di memoria, ma per
indirizzare 1Mb di memoria sono necessari 20bit (2^20=1Mb) e
noi abbiamo a disposizione solo 16bit; quindi i progettisti Intel
hanno introdotto un nuovo tipo di indirizzo costituito da due parti:
un SEGMENTO e un OFFSET (16bit ciascuno). Un indirizzo valido
è nella forma SEGMENT:OFFSET, gli indirizzi sono in base
esadecimale del tipo: 35B2:C02E.
Il problema è che questo non è un indirizzo a 20 bit, ma a 32bit;
per trovare il vero indirizzo è necessare effettuare due operazioni:
moltiplicare il segmento per 10h (16) e sommarlo all'OFFSET.
I registri relativi al segmento sono : CS, DS, ES, SS, quindi un
segmento è 64K.
Il primo
programma "Hello
World!
Come da tradizione partiremo con il programma "Hello World!",
tanto per famigliarizzare con l'ambiente di sviluppo e con i primi
elementari comandi ASM. Non preoccupatevi se non capite, non è
ancora questo lo scopo.
;ASM01.ASM
.MODEL small
.STACK 100h
.DATA
MyString DB
"Ciauz
WoRld",13,10,'$'
.CODE
mov ax,SEG
MyString
mov ds,ax
mov dx,OFFSET
MyString
mov ah,09h
int 21h
mov ah,4Ch
int 21h
END
[bY_ Alessandro Polo 1999]
[modello di memoria]
[dimensione dello Stack]
[inizio del segmento dati]
[dichiarazione del Stringa]
[inizio del segmento di codice]
[ax = indirizzo del Segmento Dati]
[ds = ax]
[ds = offset del Segmento Dati]
[ ah = 09h ]
[call all'interrupt DOS]
[ ah = 4Ch ]
[call all'interrupt DOS]
[fine del programma]
Questo programmino scriverà sullo schermo il messaggio "Ciauz
WoRld", ora analizzaremo più in dettaglio i comandi usati e la
struttura del codice:
.Model
eWorld ReSearch - Assembler Tutorial
E' il modello di memoria da utilizzare nel programma, può essere:
Large (codice e dati superano i 64Kb), Compact (a differenza
dello Small, i puntatori Far possono superare i 64Kb), Medium (il
codice può superare i 64Kb), Small (non oltre i 64kb), Tiny (non
oltre i 64kb, file .COM).
.Stack
Spazio riservato per lo Stack (predefinito = 200h =1kb).
.Data
Sezione dei dati del programma, qui sono assegnati i valori alle
costanti.
MyString DB "Ciauz WoRld",13,10,'$'
Viene assegnato il testo "Ciauz World" alla variabile Message, DB
assegna il numero di byte necessari, in tutto 14: 11 per la stringa,
1 per l'invio (#13), 1 per #10 e uno per "$" che deve essere al
termine di ogni stringa dichiarata.
Nota: Mentre DB assegna un numero di byte, esistono altre
direttive come:
DW (Define Word), DD (Define Double Word), DQ (Define
Quadword), DF (Define 48bit), DT (Define TenByte).
.Code
Questa sezione è il cuore del programma: il codice sorgente.
Gli Interrupt
Analizziamo il codice del programma proposto:
Istruzione MOV ds,ax
Istruzione MOV dx,OFFSET
MyString
Istruzione MOV ah,09h
Istruzione INT 21h
Quest'istruzione sposta
il contenuto di ax nel
data segment.
Con quest'istruzione si
copia l'offset della
variabile (MyString) in
dx. (N.B. OFFSET e
SEG sono parole
riservate.)
Modifichiamo il registro
ah inserendo il valore
esadecimale 09.
Chiama l'interrupt 21h
per stampare sullo
schermo il messaggio.
eWorld ReSearch - Assembler Tutorial
Istruzione MOV ah,4Ch
Istruzione INT 21h
Copiamo il valore 4C in
ah, spiegherò il motivo
di quest'istruzione
nella sezione Interrupt.
Chiama l'interrupt 21h
per terminare il
programma.
(l'alternativa è
resettare il pc)
Gli interrupt sono delle funzioni paragonabili alle API di Windows
(anche se meno avanzate e comode) del DOS o del BIOS.
L'interrupt usato precedentemente è il 21h (fa parte del DOS), per
capire il funzionamento è necessario sapere il valore di AH
quando l'interrupt viene chiamato (AH è paragonabile alle variabili
date alle API). Consultando il manuale in relazione all'interrupt
21h si cerca il valore 09h e si scopre che la funzione è: stampa
una stringa nell'output del monitor, la stringa stampata è in DS:
DX (infatti c'è il nostro messaggio).
Le funzioni Interrupt sono salvate nel primo Kbyte di RAM, cioè
dall'indirizzo 000h a 3FFh, ogni funzione è di 4 byte, quindi è
possibile calcolare dove si trovi ogni interrupt in memoria: 4(byte)
* 21h (interrupt) = 84h (indirizzo in memoria).
Secondo Esempio
Questo programma è molto simile a quello precedente nel senso
che ha lo stesso fine: stampare qualcosa sullo schermo.
;ASM02.ASM
SEG_A SEGMENT
ASSUME CS:SEG_A,
DS:SEG_A
ORG 100H
Ciauz PROC FAR
PARTENZA: JMP
START
MyString DB "Ciauz
WoRld",13,10,'$'
START:
mov dx,OFFSET
MyString
mov ah,09h
[bY_ Alessandro
Polo 1999]
[salta a START]
[dichiarazione del
Stringa]
[ds = offset del
Segmento Dati]
[ah = 09h]
eWorld ReSearch - Assembler Tutorial
int 21h
RETN
Ciauz ENDP
SEG_A ENDS
END PARTENZA
[chiamata
l'interrupt]
Rispetto all'esempio precedente qui manca il Data Segment e lo
Stack Segment. D'altra parte questo non è un EXE ma un COM ed
infatti è necessario specificarlo al momento del"linking".
Le Funzioni
La call:
message db 'Ciauz
WoRld','$'
mov dx, offset message
call DisplayString
La Routine:
DisplayString:
mov ax,cs
mov ds,ax
mov ah,9 ; DOS
FUNCTION: display
message
int 21h ; Call the DOS
interruptmov ah,
ret
eWorld ReSearch - Assembler Tutorial
Linker, OBJ
e file EXE
Una volta terminato di scrivere il programma ASM e salvato il file
xxx.ASM, è necessario prima compilare il programma e poi
linkarlo; compilando il programma verrà creato un file oggetto (.
OBJ) che deve essere linkato per creare il vero e proprio
eseguibile. Il file risultante è apparentemente un ammasso di
caratteri ASCII senza senso, ma in realtà esiste una relazione tra
il file EXE e il codice ASM, infatti è anche possibile tornare
dall'eseguibile al sorgente tramite un Disassemblatore oppure un
Debugger (questo permette anche di modificare le istruzioni in
Runtime cioè mentre il programma stà funzionando).
Ad esempio l'istruzione JNE X8(Jump if Not Equal) ha come valore
75cb, quando si vuole patchare un programma, cioè modificare
l'eseguibile per aggirare uan protezione (ad esempio) è necessario
aprire il file e cambiare alcuni valori di questi caratteri ASCII
(potremmo semplicemente modificare 75 a 74 per esempio).
Comunque tratterò questi argomenti in altra sede.
All trademarks are property of their respective owners.
Any tools listed and available in zip package is free and was downloaded from the
Internet.
You are authorized to copy, redistribute and print this paper, keeping Author's
credits visible and without changing the document's content.
Author is not responsible for any consequences or damages related in any way to
this material.
Last update: 12/1999
ReSearch
Home
open source 1999 | by Alessandro Polo
eWorld
Network
Scarica

Assembler Tutorial