IL sistema binario
*** SISTEMA DECIMALE, BINARIO
e ESADECIMALE ***
L'uomo e' abituato a ragionare in base 10, anche se poi e' andato ad
inventare i secondi che sono 60 in un minuto che si ripete 60 volte in un ora...
ecc... Il computer ragiona SOLO in base 2 (vi ricordate 1 e0...). Una via di
mezzo tra uomo e macchina può essere il sistema esadecimale. Esso utilizza 16
simboli: 0 1 2 3 4 5 6 7 8 9 A B C D E F ed e' come vedremo molto più' compatto
dei quello binario. Decimale. Base 10. 0 = 10^0*0 1 = 10^0*1 53 =10^1*5 + 10^0*3
106 = 10^2*1 + 10^1*0 + 10^0*6 Binario. Base 2. 0 = 2^0*0 = 0 1 = 2^0*1 = 1 53
=2^5*1 + 2^4*1 + 2^3*0 + 2^2*1 + 2^1*0 + 2^0*1 =110101 106 = 2^6*1 + 2^5*1 +
2^4*0 + 2^3*1 +2^2*0 + 2^1*1 + 2^0*1 = 1101010 Esadecimale .Base 16. 0 = 16^0*0
= 0 1 = 16^0*1 = 1 53 =16^1*3 + 16^0*5 = 35 106 = 16^1*6 + 16^0*A = 6A
CONVERSIONE DI BASE Decimale --> binario, esadecimale Dividere il numero da
convertire per la base in cui lo si vuole convertire. Moltiplicare il resto per
la base, continuare fino ad arrivare allo 0. Es: Esadecimale 106/16 = 6,625
0.625*16 = A ( 10 = A in Hex) 6/16 = 0,375 0.375*16 = 6 107(dec) = 6B(hex)
Binario 106/2 = 53 0 53/2 = 26.5 0.5*2 = 126/2 = 13 0 13/2 = 6.5 0.5*2 = 1 6/2 =
3 0 3/2 = 1.5 0.5*2 = 1 1/2 = 0.5 0.5*2 = 1 106(dec) = 1101010(bin) Esadecimale
--> binario Spezzare il numero in parti da 4 bit. Convertire le parti secondo
la seguente tabella: 0000 = 0 0100 = 4 1000 = 8 1100 = C 0001 = 1 0101 = 5 1001
= 9 1101 = D 0010 = 2 0110 = 6 1010 = A 1110 = E 0011 = 3 0111 = 7 1011 = B 1111
= F Es: 1000000000111101(bin) 1000 0000 0011 1101(bin) 8 0 3 D (hex) 803D(hex)
*** BIT, BYTE, WORD e DWORD *** Un bit e' la più' piccola porzione di
informazione che possiamo ottenere. Il bit puo' assumere valore 1 o 0. Per la
CPU questi valori sono rappresentati da tensioni diverse: 0 = da 0 a 2.5V 1 = da
2.5 a 5V 8 bit formano un byte. Un byte puo' assumere fino a 2^8 = 256 valori
diversi. 00000000 = 2^7*0 + 2^6*0 + 2^5*0 + 2^4*0 + 2^3*0 + 2^2*0 + 2^1*0 +
2^0*0 = 0 00100101 = 2^7*0 + 2^6*0 + 2^5*1 + 2^4*0 + 2^3*0 + 2^2*1 + 2^1*0 +
2^0*0 = 37 11111111 = 2^7*1 + 2^6*1 + 2^5*1 + 2^4*1 + 2^3*1 + 2^2*1 + 2^1*1 +
2^0*1 = 255 16 bit formano una word. Una word puo' assumere 2^16 =65.536 valori
diversi. Le word di solito sono rappresentate da 4 cifre esadecimali. 0000 =
16^3*0 + 16^2*0 + 16^1*0 + 16^0*0 = 0 1A5D = 16^3*1 + 16^2*A + 16^1*5 + 16^0*D =
6.749 FFFF = 16^3*F + 16^2*F + 16^1*F + 16^0*F = 65.536 32 bit formano una dword.
Una dword puo' assumere 2^32 = 4.294.967.296 valori. Le dword di solito sono
rappresentate da 8 cifre esadecimali 00000000 = 16^7*0 + 16^6*0 + ... + 16^1*0
+16^0*0 = 0 FFFFFFFF = 16^7*F + 16^6*F + ... + 16^1*F + 16^0*F = 4.294.967.296
*** THE INTEL PROCESSOR
***
Tutta la famiglia dei processori Intel (x86) si basa ed e' compatibile con
il primo processore di questo tipo: l'8086. L'8086 e' un processore a 16 bit
quindi i suoi registri potranno contenere al massimo 16 bit di informazione. I
processore più' moderni quali 80486, Pentium e Pentium II sono processori a 32
bit. Intel rilascerà' a meta del 2000 anche il Merced a 64 bit, ma fino allora
tratteremo solo fino a registri a 32 bit. Quindi per poter conoscere come
funziona un processore Pentium e' necessario partire dal suo bis-bis-nonno:
8086. La struttura interna dell'8086 si presenta grossomodo cosi: PROCESSOR RAM
------------------------------- ------------------------------- | | | | |
|
------- ---------- | | Segmento | Segmento | | | | | Banco | | |
| | | | ALU | <---- | dei | | | Istruzioni | Dati | | | | ----> |
Registri | | | | | | ------- ---------- | -------------------------------
| ^| ^| | |^ |^ | || || | || || |
-|-----------------|-------------------|----------------|--> |
<----------------------------------------------------------- | | BUS
------------------------------- Il banco dei registri e' cosi'
suddiviso: ----------------- ------------------- | AH | AL | AX \
| IP | Instruction |-----------------| | | | Pointer | BH | BL |
BX | common |-------------------| |-----------------| | registers
| O D I T S Z A P C | Flags | CH | CL | CX |
------------------- |-----------------| | | DH | DL | DX /
|-----------------| | SI | \ |-----------------| | string registers |
DI | / |-----------------| | SP | \ |-----------------| | stack
registers | BP | / |-----------------| | CS | \ |-----------------| |
| DS | | |-----------------| | segment registers | ES | |
|-----------------| | | SS | / ----------------- AX, BX, CX, DZ
sono registri a 16 bit; AL e AH, ecc sono registri a 8
bit. Nei processori successivi al 80386 ci sono anche registri a 32 bit.
La loro denominazione e' semplicissima: basta preporre una E sul registro
desiderato. es: EAX, EBX. EBP, ESP, EIP, ecc. Vediamo ora a cosa servono i
registri della cpu. AX...DX sono i registri comuni. Sono usati come accumulatori
temporanei. SI e DI sono i registri per le stringhe. Essi sono usati per
confrontare, copiare, spostare le stringhe. SP e BP sono i registri per lo stack.
Lo stack e' un pila (LIFO) di dati. LIFO vuol dire Last In First Out. Per
spiegarci meglio la coda che fate al supermercato e' FIFO (First In First Out)
cioe' ilprimo che si mette in fila sara' il primo ad uscire. Lo stack e' il
contrario: il primo che entra sara' l'ultimo ad uscire. Un po' come un cestino
per la carta... quando lo svuoti le prime cose che escono sono le ultime che hai
buttato. Il registro SP (Stack Poiter) punta all'ultimo elemento dello stack
(quindi puntera' al pezzo di carta che hai buttato per ultimo). Per recuperare
dati che si trovano in mezzo allo stack, basterà' spostare questo puntatore. Il
registro BP punta alla base dello stack ed e' usato per i record di attivazione
delle funzioni chiamate. CS...SS sono i registri di segmento. Vediamo che cosa
e' un segmento. La memoria gestita da un 8086 e' divisa in blocchi da 64 Kb,
poiché' puo' indirizzare solo 16 bit (2^16 = 65536 = 64 K). Il segmento
rappresenta l'indirizzo del blocco utilizzato in quel momento. Per conoscere la
posizione all'interno del segmento, si usa l'offset, rappresentato dal registro
IP. Nei processori a 32 bit i valori cambiano... provate a calcolare quanto si
puo' indirizzare.... cmq le cose si complica un po' e non e' questo l'intento
del tutorial. Ecco in dettaglio i registri di segmento: CS Code segment.
Contiene il codice da eseguire. DS Data segment. Contiene i dati da trattare:
stringhe, variabili, ecc. ES come DS ma usato per confrontare le stringhe. SS
Stack Segment. IP e' l'instruction pointer. Esso punta alla prossima istruzione
che dovra' essere eseguita. Le Flags possono assumere valore 1 o 0 (on or off).
C = Carry flag P = Parity flag A = Auxilary carry flag Z = Zero flag S = Sign
flag (+ or -) O = Overflow flag I = Interrupt enable D = Direction flag T = Trap
flag La piu' importante e' sicuramente la ZERO flag. Essa e' settata dopo ogni
confronto. Assume il valore 0 oppure 1 a seconda del tipo di istruzione usata
per effettuare il confronto. All'inizio abbiamo parlato delle istruzioni
assembly. Vediamone ora il significato di alcune di esse. ** CALL ** Utilizzo:
CALL destinazione Es.: CALL 004DF856 ---> esegue la sub 004DF856 subroutine:
004DF856 ... 004DF857 ... ....... 004DFA21 RET ---> ritorna all'istruzione
successiva a CALL Esegue una subroutine alla "destinazione" e ritorna
quando incontra RET. ** CMP ** Utilizzo : CMP registro1, registro2 CMP memoria,
registro CMP registro, memoria Es.: CMP eax, ebx Confronta due registri e
assegna il valore 1 al flag ZF (Zero Flag) se i registri sono uguali, altrimenti
lascia 0. Varianti: CMPSB Sorgente e' messo in DS:SI e destinazione in ES:DI.
CMPSW Come sopra solo che compara una word al posto di un byte. ** DEC
**Utilizzo : DEC registro Es.: DEC eax Diminuisce di 1 il valore del
"registro". (vedi anche INC). ** DIV ** Utilizzo : DIV registro1,
registro2 Es.: DIV eax, 014 Divide registro1 per registro2. Il risultato viene
>Es.: INC eax Aumenta di 1 il valore del "registro". (vedi anche
DEC). ** INT ** Utilizzo : INT numero_dell_interrupt Es.: INT 21 Effettua una
chiamata all' Interrupt desiderato. ** Jump ** Utilizzo: Jxx indirizzo Es.: Jxx
004056DE Esistono molti tipi di Jump e, a seconda del tipo le "xx" di
Jxx cambieranno. Opcode Mnemonic Meaning Jump Condition 77 JA Jump if Above CF=0
and ZF=0 73 JAE Jump if Above or Equal CF=0 72 JB Jump if Below CF=1 76 JBE Jump
if Below or Equal CF=1 or ZF=1 72 JC Jump if Carry CF=1 E3 JCXZ Jump if CX Zero
CX=0 74 JE Jump if Equal ZF=1 7F JG Jump if Greater (signed) ZF=0 and SF=OF 7D
JGE Jump if Greater or Equal (signed) SF=OF 7C JL Jump if Less (signed) SF != OF
7E JLE Jump if Less or Equal (signed) ZF=1 or SF!=OF JMP Unconditional Jump
unconditional 76 JNA Jump if Not Above CF=1 orZF=1 72 JNAE Jump if Not Above or
Equal CF=1 73 JNB Jump if Not Below CF=0 77 JNBE Jump if Not Below or Equal CF=0
and ZF=0 73 JNC Jump if Not Carry CF=0 75 JNE Jump if Not Equal ZF=0 7E JNG Jump
if Not Greater (signed) ZF=1 or SF!=OF 7C JNGE Jump if Not Greater or Equal (signed)
SF != OF 7D JNL Jump if Not Less (signed) SF=OF 7F JNLE Jump if Not Less or
Equal (signed) ZF=0 and SF=OF 71 JNO Jump if Not Overflow (signed) OF=0 7B JNP
Jump if No Parity PF=0 79 JNS Jump if Not Signed (signed) SF=0 75 JNZ Jump if
Not Zero ZF=0 70 JO Jump if Overflow (signed) OF=1 7A JP Jump if Parity PF=1 7A
JPE Jump if Parity Even PF=1 7B JPO Jump if Parity Odd PF=0 78 JS Jump if Signed
(signed) SF=1 74 JZ Jump if Zero ZF=1 ** MOV ** Utilizzo: MOV destinazione,
sorgente Es.: MOV eax, ebx Copia il valore di [sorgente] in [destinazione].
Varianti: MOVSB Sorgente e' messo in DS:SI e destinazione in ES:DI. MOVSW Come
sopra solo che copia una word al posto di un byte. ** MUL ** Utilizzo : MUL
registro1, registro2 Es.: MUL eax, 014 Moltiplica registro1 per registro2. Il
risultato viene messo in registro1. ** NOP ** Utilizzo: NOP Es.: NOP Non esegue
alcuna istruzione. (e allora a che serve??? Serve serve...) se devi eliminare
una call, che fai ?? la cancelli ?? no ! Usi una NOP... ** POP ** Utilizzo : POP
destinazione Es.: POP eax Toglie dallo stack l'ultimo elemento e lo mette in
"destinazione". ** PUSH ** Utilizzo : PUSH sorgente Es.: PUSH eax PUSH
004056FD Mette in cima allo stack "sorgente". ** REP ** Utilizzo : REP
Es.: REPZ CMPSW <--- istruzione ripetuta Ripete l'esecuzione di una
istruzione su stringhe "while" CX != 0. Ad ogni passo CX e'
decrementato di 1. Varianti REPE Es.: REPE CMPSB compara ogni byte in una
stringa "while" sono uguali. REPZ Ripete "while" zero flag
e' 0 (off) "while" ha lo stesso significato del C. quindi in italiano
"while" CX != 0 si potrebbe tradurre "continua finche CX diventa
0" ** RET ** Utilizzo : RET Es.: RET Ritorna da una procedura. (vedi CALL)
** TEST ** Utilizzo : TEST destinazione, sorgente Es.: TEST eax, eax Esegue un
AND logico tra destinazione e sorgente. Aggiorna i flag ma non salva il
risultato .
Scarica il testo appena letto in formato ZIP
Se non hai WinZip puoi scaricarlo cliccando direttamente Qui