2016-07-05 49 views
5

Sto assemblando utilizzando MASM 14.0 e sono confuso con l'output del codice seguente.In che modo ASM sa che un'operazione aritmetica è firmata o non firmata?

TITLE Exercise 4 from chapter 4 

; Author : Saad Ahmed 

INCLUDE Irvine32.inc 

.code 
main PROC 

mov eax, 0 
mov al, 255 
add al, 1 
call DumpRegs  ; Display registers 

mov al, 127 
add al, 1 
call DumpRegs  ; Display registers 

exit 
main ENDP 
END main 

Entrambe le operazioni aritmetiche sono fatte su numeri interi senza segno 255 e 127.

Tuttavia, la CPU sta trattando la prima operazione 255, come un interi senza segno e l'impostazione del carry flag, che sarebbe accaduto quando si aggiunge 1 di un unsigned 255.

I flag di stato complete sono CF = 1 SF = 0 ZF = 1 dI = 0 AF = 1 PF = 1 con eax come 0

Ma, la seconda operazione considera il 127 essere un intero con segno dato che sta impostando il flag di overflow, che woul d succede se aggiungi 1 a +127.

I flag di stato completi sono a CF = 0 SF = 1 ZF = 0 = 1 DI AF = 1 PF = 0 con EAX come 0.

La domanda è: come fa la CPU decide che la prima operazione è stata fatto su un 255 senza segno, mentre l'altro era su un intero con segno?

+0

add/sub sono gli stessi per il complemento di unsigned vs. 2. Vedi [Understanding Carry vs. Overflow conditions/flags] (http://teaching.idallen.com/dat2343/10f/notes/040_overflow.txt). Questo viene dal [wiki tag x86] (http://stackoverflow.com/tags/x86/info). –

risposta

5

Ciò che è bello del complemento a due è che la CPU non ha bisogno di sapere.

Si aggiunge semplicemente ai byte senza segno.

Il flag di trasporto è impostato perché 255 + 1 non si adatta in 8 bit (ovviamente).

Il flag di overflow viene impostato perché il MSB di entrambi gli operandi è 0, e la MSB del ouput è 1 - indica che se si considera questo essere firmato aritmetica, si è traboccato. Se consideri l'aritmetica non firmata, dovresti semplicemente ignorare la bandiera. Vedi this wikipedia article.

+3

Vero per addizione e sottrazione ... per la moltiplicazione e la divisione, ci sono istruzioni separate per firmato e non firmato. –

+0

Grazie! Sì, ho ricercato e credo che la CPU abbia impostato tutti i flag di stato dopo un'operazione aritmetica utilizzando un insieme di regole. Dobbiamo decidere quali bandiere sono rilevanti e quali ignorare. Quindi, come hai detto, stavo considerando l'operazione aritmetica senza firma sopra, quindi dovrei semplicemente ignorare la bandiera. – Saad

+1

@ AdamD.Ruppe: Nel caso di IMUL e MUL entrambi possono operare su valori con segno e senza segno. L'IMUL è generalmente visto come la forma multioperante di MUL. –

9

Per l'addizione (e la sottrazione) utilizzando il complemento a due non vi è alcuna nozione di segno o non firmato per quanto riguarda la logica. Moltiplicare e dividere, sì, a causa dell'estensione del segno richiesta.

Prendere tutte le combinazioni di numeri a 3 bit da 000 a 111 e aggiungerle a tutte le combinazioni di numeri a 3 bit, qualcosa di gestibile. Magari scrivi un programma se vuoi o fallo a mano. O fai solo le casse d'angolo. Per ciascun esame, ciascun operando come firmato o non firmato utilizza due complementi. Noterai che la stessa aggiunta funziona. 1 + 110 = 111. Ora è che 1 + (-2) = -1 o era 1 + 6 = 7. Entrambi funzionavano.

Il flag di carry è il trabocco UNSIGNED, la bandiera V è l'overflow FIRMATO, è per questo che si calcola sia così l'utente, chissà se quelli sono firmati o numeri senza segno può scegliere il diritto condizionato. Ed è per questo che hai firmato il salto se maggiore o uguale rispetto a un salto senza segno se maggiore o uguale.

È la bellezza di due complementi che fa funzionare tutto.

Moltiplicare (e dividere) è diverso, perché è necessario firmare l'estensione. Moltiplicare in binario ha una bella caratteristica, nel senso che se ci pensate

abcd 
* 0011 
======= 
    abcd 
    abcd 
0000 
0000 
======= 

Un po 'è 1 o 0, quindi si stanno moltiplicando il numero superiore da uno o pari a zero, si sia aggiunge spostato o dont. Ma notate anche che molto molto rapidamente andrete in overflow. Sappiamo dalla scuola elementare che n^x * n^y = n^(x + y).Se i registri sono larghi con Z di larghezza, le posizioni di bit più significative degli operandi non possono essere maggiori di Z quando vengono aggiunte altrimenti si rovesciano. Quattro bit 0010 * 0010 dovrebbero funzionare ma 0010 * 1000 andrà in overflow. Il modo giusto è che il risultato è due volte più largo degli operandi.

Quindi cosa succede se voglio moltiplicare 1111 * 0010?

Questo è fondamentalmente

0000 
    1111 
    0000 
+0000 
======== 
0011110 

attesa era che un 15 (0b1111) o -1 (0b1111)? -1 * 2 = -2, che non è quello che abbiamo ottenuto in precedenza, abbiamo fatto un moltiplicano non firmato per fare un firmato moltiplicano dobbiamo firmare estendere e lanciamo bit al largo della sinistra

11..1111 
*00..0010 
=========  
00000000 
1111111 
000000 
00000 
========= 
11111110 

e che dà la risposta giusta per una moltiplicazione firmata di due registri a quattro bit 1111 e 0010.

L'aggiunta funziona perché interessa solo una colonna. Ogni colonna ha un riporto, due operandi un risultato e un risultato. E poi puoi farlo a cascata quanto vuoi tu. Con un singolo bit hai 0 e 1. Lo zero è solo zero non più o meno zero, l'1 può essere un +1 o un -1. Trovo più facile lavorare attraverso le combinazioni con più di una colonna, ma potrebbe essere fatto. Per oltre il riporto in è un 0 in modo non ho bisogno di rappresentarla operando A, operando b, eseguire, e il risultato

00 00 0 + 0 = 0 
01 01 0 + 1 = 1; 0 + (-1) = -1 
10 01 1 + 0 = 1; (-1) + 0 = -1 
11 10 1 + 1 = 0 unsigned overflow. -1 + 1 = 0, 1 + -1 = 0, -1 + -1 = 0 signed overflow 

Tecnicamente tutti quelli firmati erano un overflow firmato in questo ultimo caso, e questo è il caso speciale con cui trattate per un numero qualsiasi di bit, prendete un registro a tre bit 100 + 100 = 000 + esegui 1 è un 4 + 4 = 0 di overflow senza segno o è un -4 + -4 = 0 con un overflow firmato? Questo è il motivo per cui è più facile vedere quando si usano alcuni bit e si passano attraverso le combinazioni che lanciano il caso problema di 1 e quindi tutti gli zeri.

Un overflow firmato è quando il carry in della colonna più significativa non corrisponde al completamento. un overflow senza segno è quando l'esecuzione del msbit è uno.

La sottrazione in logica viene eseguita con l'aggiunta, sappiamo dalla scuola elementare che a - b = a + (-b) e sappiamo dalle classi di programmazione che prendere il negativo usando due si completano e si aggiungono. Bene, questo funziona alla grande, possiamo semplicemente invertire il secondo operando e invertire il carry-in dell'isbit rendendolo uno o invertirlo e aggiungerne uno. Ed è così che funziona. L'esecuzione è a volte invertita che esce dall'alluminio per indicare un prestito. Devi guardare le combinazioni di bandiera per capirlo, alcuni processori invertono il portare fuori alcuni. A volte si può dire dalla sottrazione con un prestito se il proprio ISA ha questa istruzione.

So TL: DR ... coperto più di quello che hai chiesto.

+0

se il multiplo è N bit in N bit fuori, non è necessario firmare l'estensione destra? quindi non è un segno specifico. 1111 * 0010 = 1110 è un overflow se non firmato ma la risposta giusta se firmata (fortuna senza fortuna). –