|
|||||||
|
|
|
![]() |
|
|
Strumenti |
|
|
#1 |
|
Member
Iscritto dal: Jul 2004
Città: Mn
Messaggi: 56
|
[ASSEMBLY] Modifica di un piccolo programma (calcolatore): help!
Salve a tutti, avrei bisogno di un po' di aiuto per modificare un semplice programma: è un piccolo calcolatore per numeri interi (dos 16 bit), al quale vorrei aggiungere il supporto per numeri floating point, e magari una semplice interfaccia grafica.
Come dovrei procedere? Non so proprio da dove partire! Grazie per l'attenzione, e per ogni eventuale suggerimento... |
|
|
|
|
|
#2 |
|
Member
Iscritto dal: Jul 2004
Città: Mn
Messaggi: 56
|
up!
|
|
|
|
|
|
#3 | |
|
Senior Member
Iscritto dal: Feb 2002
Messaggi: 906
|
Quote:
.386 .387 e ricerca su google "i80x87" questi sono i miei studi all'epoca: alcune istruzioni che scomodano la fpu: finit fld realnum1 fld realnum2 ;fmulp st(1), st(0) ;moltiplicazione ;fsubp st(1), st(0) ;sottrazione ;faddp st(1), st(0) ;addizione fdivp st(1), st(0) ;divisione prima devi prendere in input 2 numeri mettere una var tipo "place" che identifica il punto. place la puoi inizializzare a 2 cioè due cifre dopo il punto oppure a 3 cifre dopo il punto. mov segno,0 mov cx,0 mov places,cx ;places sono le cifre dopo la virgola ;XOR BX, BX ; azzera BH MOV eSI, 10 ; SI 10 (base) XOR DI, DI ; azzera DI XOR eAX, eAX ; azzera AX ;MOV BX, offset num1 ; BX indirizzo iniziale STRINGA XOR CX, CX mov di,0 ciclolo2q: mov dl,BYTE PTR num1[di] cmp dl,'-' ;controllo se c'è il meno je nospq ;e incremento places cmp dl,'.' ;controllo se c'è il punto je incpuntoq ;e incremento places cmp dl,' ' je finest2q cmp dl,'$' je finelo2q cmp places,0 ;controllo se places è maggiore 0 ja inccpq ; e se è >0 vuol dire che sto dopo il punto quindi inc places altro code: ;;;;;;;;;;;;;;;;;;;;CONTROLLO PUNTIO ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;,, ;lea bx,realnum1 ;push bx mov int1,0 mov int1,eax finit ;carica fpu fild int1 ;carica intero senza punto = 121 binario mov cx, 0 @@cicla2: cmp cx, places ; se cx = 3, ovver le cifre dopo ; la il punto = 987 je @@done2 fld realTen ;carica 10.0 fdivp ;dividi la cifra 12.987 ora così 12987 per ;quante cifre dopo il punto, in questo caso 3 ; quindi: cx=1 12987 / 10.0 = 1298.7 ; cx=2 1298.7 / 10.0 = 129.87 ; cx=3 129.87 / 10.0 = 12.987 inc cx jmp @@cicla2 @@done2: ; pop bx ; mov dx,offset realnum1 ; mov di,dx ; fstp dword ptr[bx] ;realnum1 vale 12.987 ; fstp realnum1 ;vale 12.987 fwait ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ret ora sai cosa devi fare... manca solo la parte + difficile ftoa proc tuo code qui... pseudo code 0. prendi la stringa 1. il valore è moltiplicato * 10 per ogni cifra che incontr dopo il punto o la virgola (dipende cosa vuoi) 2. Usa i comandi fist per arrotondare ad integer. 3. Dividi il resto per 10 4. se il valore è negativo metti il "-" davanti 5. il punto o la virgola la inserisci per quanto hai scelto dopo 2 o 3 o 4 tipico di "place" ... e quì ftoa endp buon studio ciao Edit: sto vedendo che ho scritto anche troppo potrebbe confonderti. La cosa da sapere in verità è molto semplice: leggi la stringa primo numero e secondo numero, se essa ha il punto o la virgola la porti ad integer moliplando per 10 fai il risultato è la riporti ad integer dividendo per 10 dopo la virgola. Insomma come si fà alla scuola... Edit 2: le mie intestazioni che possono aiutarti: ------------------ Risultato dd 0,0 Numero1 dd 0,0 Numero2 dd 0,0 RealNum1 dd 0,0 RealNum2 dd 0,0 firstInteger dd ? secondInteger dd ? thirdInteger dd ? tempStr db 25 dup (?), '$' Int1 dd ? Int2 dd ? realTen dd 10.0 integerTen dd 10 places dw ? mulTen dd 10.0 Temp dd 0 Risultato1 dd 0,0 Risultato2 dd 0,0 meno db 0 segno db 0 puntone db 0 meno2 db 0 segno2 db 0 puntone2 db 0 ------------------ Ultima modifica di okay : 24-05-2007 alle 09:26. |
|
|
|
|
|
|
#4 |
|
Senior Member
Iscritto dal: Feb 2002
Messaggi: 906
|
un'altro contributo:
Architettura interna L'8087 NDP è interamente strutturato su due unità di processo indipendenti: la Control Unit CU, che provvede alla gestione del bus, alla lettura e decodifica delle istruzioni e al trasferimento di dati con la memoria, e la Numeric Execution Unit NEU, che interpreta ed esegue le istruzioni passatele dalla CU. Le due unità sono in grado di operare in modo indipendente, permettendo alla CU di mantenere la sincronizzazione con la CPU nel fetching delle istruzioni, mentre la NEU è impegnata nel processamento della precedente istruzione. Per esempio, se si desidera calcolare la radice quadrata sul terzo registro dal top-of-stack, basta disporre le seguenti istruzioni: FXCH ST(3) (scambio di ST(0) con ST(3)); FSQRT (ST(0) = Square Root (ST(0)); FXCH ST(3) (scambio di ST(0) con ST(3)). Tag Word La Tag Word riporta, in un campo di due bit assegnato a ogni registro dello stack, lo stato caratteristico, permettendo di ottimizzare il funzionamento dell’NDP. Instruction e Data Pointer Ogniqualvolta la NEU esegue una istruzione, la CU salva in questi registri l’indirizzo e il codice operativo dell’istruzione in atto, con l’indirizzo dell’eventuale operando in memoria. Nel caso si origini una Exepition, la routine di servizio relativa può caricare in memoria questi registri (FSTENV) e dal loro esame ricavare delle informazioni concernenti l’istruzione che ha generato la segnalazione di errore. Tipologie Le istruzioni dell’8087 possono essere suddivise in base al tipo di operazioni svolte, in sei gruppi fondamentali: trasferimento dati, operazioni aritmetiche, confronti, operazioni trascendenti, caricamento di costanti e istruzioni di controllo della CPU. La tipica istruzione NDP accetta uno o due operandi in ingresso, li processa e produce un risultato in uscita. Gli operandi sono tipicamente costituiti dal contenuto di registri interni o di una locazione di memoria: in alcune istruzioni gli operandi sono predefiniti (per esempio, l’istruzione FSQRT opera la radice quadrata del contenuto del registro top-stack), in altre sono definibili dall’operatore mentre quelle a due operandi accettano tipicamente un operando "esplicito" e uno implicito, che è usualmente il top-of-stack. Nel caso di due operandi in ingresso, uno (tipo "source") non è modificato dall’operatore mentre l’altro (tipo "destination") è sostituito con il valore del risultato, con la logica: (destination) = (destination) < op > (source) Istruzioni di trasferimento dati Queste istruzioni permettono di trasferire dati all’interno dello stack di registri o tra il registro top-of-stack e la memoria. Qualunque dei sette tipi di formato può essere convertito in Temporary Real e caricato (push) nello stack con un unica operazione e nello stesso modo può essere riportato nella memoria (pop): queste operazioni di trasferimento aggiornano automaticamente la Tag Word in modo che rifletta il contenuto del registro a seguito dell’istruzione effettuata. Esse comprendono: FLD source: Carica in ST(0) un operando sorgente in una qualunque notazione real e lo converte in temporary: l’operando può essere un altro registro dello stack (source = ST(i)) o un dato in memoria. FST dest.: Trasferisce (store) il contenuto di ST(0) nel registro destinazione (registro o memoria), operando un arrotondamento se il formato del destinatario è short o long. FSTP dest.: Trasferisce nel destinatario il contenuto di ST(0) ed esegue un pop dello stack incrementando ST. In questo caso è ammesso il trasferimento di un Temporary Real. FXCH ST(i)): Scambia il contenuto del registro destinazione ST(i) con il contenuto di ST(0) (top-of-stack). FILD source: Converte un operando sorgente in memoria dal formato integer in Temporary Real e lo carica (push) nello stack. FIST dest.: Converte in integer il contenuto di ST(0) e lo trasferisce nel destinatario in memoria. FISTP dest.: Come la precedente, con un pop dello stack dopo il trasferimento. FBLD source: Converte un dato BCD compattato proveniente dall’operando source e lo carica (push) nello stack. FBSTP dest.: Trasferisce nel destinatario il contenuto di ST(0) convertito in BCD compattato, ed esegue il pop dello stack. Istruzioni aritmetiche In questo gruppo sono comprese istruzioni aritmetiche semplici, quali somma, sottrazioni, moltiplicazione e divisione e operazioni più complesse, quali la radice quadrata e l’arrotondamento. Nel caso l’istruzione preveda due operandi in ingresso, sono previsti differenti modi di indirizzamento. In aggiunta alle quattro operazioni elementari, sono previste, per la sottrazione e la divisione, due istruzioni inverse, che permettono di commutare l’ordine degli operandi. Indirizzamento Mnemonico Operandi destin.,source Codice ASM-86 Stack Fop ST(1), ST(0) FADD Registro Fop ST(i), ST(0) o ST(0), ST(i) FADD ST, ST(3) Registro Pop FopP ST(i), ST(0) FADDP ST(2), ST Real memoria Fop ST, short/long real FADD ALFA Integer mem. FIop ST, word/short integer FIADD BETA op = ADD destination ¬ destination + source SUB destination ¬ destination - source SUBR destination ¬ source - destination (Reverse) MUL destination ¬ destination * source DIV destination ¬ destination / source DIVR destination ¬ source / destination (Reverse) Nella forma indirizzamento "stack" gli operandi sono definiti implicitamente nel top-of-stack ST(0) (source) e nel registro ST(1) (destination): il risultato della somma è caricato in ST(1) e dopo è eseguito il pop dello stack, che espelle il primo operando, lasciando nella sommità dello stack il risultato. Nel modo registro, che è una generalizzazione del modo precedente, un qualsiasi altro registro ST(i) dello stack può essere abbinato a ST(0), sia come source sia come destination. In questo caso il pop finale non è implicito, ma deve essere espressamente richiesto con il suffisso - P (registro Pop). Nei due modi d’indirizzamento con la memoria (real e integer), il dato source è indirizzato secondo gli usuali metodi di indirizzamento previsti dall’8087, mentre l’operando destination è, per definizione, il top-of-stack ST(0). Le istruzioni aritmetiche comprendono. FADD (Add real) FADDP (Add real & pop) FIADD (Integer Add) Eseguono la somma dell’operando sorgente con il destinatario e memorizzano in questo il risultato. FSUB (Subtract real) FSUBP (Subtract real & Pop) FISUB (Integer Subtract) Sottraggono l’operando sorgente dal destinatario e memorizzano in questo il risultato. FSUBR (Subtract real Reverse) FSUBRP (Subtract real Reverse & Pop) FISUBR (Integer subtract Reverse) Sottraggono dall’operando sorgente il destinatario e memorizzano in questo il risultato. FMUL (Multiply real) FMULP (Multiply real & Pop) FIMUL (Integer Multiply) Moltiplica il sorgente con il destinatario. FDIV (Divide real) FDIVP (Divide real & Pop) FIDIV (Integer Divide) Esegue la divisione usando il destinatario come dividendo e il sorgente come divisore. FDIVR (Divide real reverse) FDIVRP (Divide real Reverse & Pop) FIDIVR (Integer Divide Reverse) Esegue la divisione usando il sorgente come dividendo e il destinatario come divisore. FSQRT (Square Root) Sostituisce il contenuto del top-of-stack con la sua radice quadra. FSCALE (Scale) Interpreta il valore contenuto in ST(1) come un integer e lo somma all’esponente di ST(0), realizzando in pratica l’operazione ST(0)-ST(0)+2 FPREM (Partial Remainder) Riporta il modulo della divisione ST(0)/ST(1). Può essere utilizzata per normalizzare gli argomenti delle funzioni trascendenti periodiche, come le funzioni trigonometriche. FRNDINT (Round to Integer) Arrotonda il dato contenuto in ST(0) convertendolo in integer. L’arrotondamento è eseguito in accordo con quanto programmato nella Control Word. EXTRACT (Extract Exponent e Significant) Decompone il numero in ST(0) nella sua parte esponente e nella parte significativa, che è caricata nello stack. È utile, abbinata all’istruzione FBSTP, per convertire un numero reale in una rappresentazione decimale (per visualizzazioni o stampe). FABS (Absolute value) Sostituisce il contenuto di ST(0) con il suo valore assoluto, rendendolo positivo (S ¬ 0). FCHS (Change Sign) Cambia il segno al contenuto di ST(0). Istruzioni di comparazione Ognuna di queste istruzioni analizza il contenuto del top-of-stack, spesso in relazione con un altro operando, e ne riporta il risultato nei Condition Flag della parola di stato. Le operazioni base comprendono il Compare, il Test (compare con zero) e l’Examine, che analizza la Tag word, il segno e il tipo di normalizzazione dell’operando. Usando l’istruzione di FSTSW (Store Status Word) è possibile ispezionare in memoria l’esito delle comparazioni effettuate e prendere le decisioni corrispondenti. Le istruzioni previste comprendono. FCOM source (Compare real) confronta ST(0) con l’operando sorgente modificando i flag Ce Cdi conseguenza. Codici NAN e infinito non possono essere confrontabili e generano C= C=1. FCOMP source (Compare real & Pop) è analoga alla precedente con aggiunta un pop dello stack. FCOMPP (Compare real & Pop doppio) confronta ST(0) con ST(1) ed esegue due pop scartando entrambi gli operandi. FICOM source (Integer Compare) converte l’operando sorgente integer in temporary real e lo confronta con ST(0). FICOMP (Integer Compare & Pop) analoga alla precedente, scarta alla fine il dato top-of-stack eseguendo un pop dello stack. FTST (Test) confronta ST(0) con zero e modifica i flag Ce Cdi conseguenza. FXAM (Examine) riporta nei flag C- C un codice che definisce le caratteristiche del contenuto di ST(0). Istruzioni trascendenti Le istruzioni di questo gruppo eseguono operazioni complesse che sono alla base delle principali funzioni trigonometriche, iperboliche, logaritmiche ed esponenziali. Opportune istruzioni devono essere premesse per ridurre eventualmente gli argomenti all’interno del range di valori accettabili: gli operandi devono comunque essere normalizzati, in caso contrario (NANs, infiniti e denormalizzati) è generato un risultato indefinito non accompagnato però dalla segnalazione di una Exception. Appartengono a questo gruppo le seguenti funzioni. FPTAN (Partial Tangent) calcola la funzione Y/X = TAN(n ), dove n è il contenuto del top-of-stack, che deve essere compreso tra 0 e p /4. Il risultato dell’operazione è memorizzato in forma di rapporto: Y è memorizzato al posto di n mentre X è caricato (push) nello stack diventando il nuovo top-of-stack. Il risultato in forma di rapporto (e l’argomento di FPATAN anch’esso sotto tale forma) consentono di ottimizzare le procedure di calcolo di altre funzioni trigonometriche, quali SIN, COS, ARCSIN e ARCOS. FPATAN (Partial Arctangent) calcola la funzione n = ARCTAN (Y/X), dove X e Y sono i contenuti di ST(0) e ST(1) rispettivamente: il rapporto Y/X in ingresso deve essere minore di 1. F2XM1 Calcola la funzione ST(0) = 2 -1, dove l’argomento in ingresso deve verificare la relazione 0ST(0)0.5. FYL2X Calcola la funzione Z = Y*LOG( X, dove X = ST(0) e Y = ST(1). FYL2XP1 Calcola la funzione Z = Y*LOG(X+1), dove X = ST(0) deve rispettare le condizioni 0<|X|<(1-( Ö 2/2)) mentre Y = ST(1). Istruzioni di caricamento costanti Ciascuna di queste istruzioni carica nello stack (push) un valore notevole, espresso in notazione Temporary Real. FLDZ (Load zero) esegue il push nello stack del valore + 0.0. FLD1 (Load one) carica il valore + 1.0 nello stack. FLDP1 (Load p ) carica nello stack il valore p . FLDL2T Carica nello stack il valore LOG10. FLDL2E Carica nello stack il valore LOGe. FLDLG2 Carica nello stack il valore LOG2. FLDLN2 Carica nello stack il valore LOG2. Istruzioni di controllo La maggior parte di queste istruzioni non sono usate nei calcoli, ma permettono alcune operazioni di controllo e di trasferimento; a eccezione di alcune, queste operazioni sono svolte dalla CU e non richiedono necessariamente di essere precedute dall’istruzione di WAIT perché possono essere eseguite mentre la NEU è ancora impegnata nel processamento della sua istruzione. Le istruzioni comprendono. FINIT Inizializza il processore in modo equivalente al Reset Hardware, con l’eccezione di non modificare la sincronizzazione dei fetch con la CPU. FDISI Disabilita il flag di Interrupt Enable, impedendo all’NDP di inviare richieste di interruzione per exception. FENI Riabilita la richiesta di interruzione. FLDCW Carica nella Control Word l’espressione contenuta nell’operando sorgente. FSTCW Trasferisce la Control Word nel registro destinatario (in memoria). FSTSW Trasferisce nella locazione destinataria la Status Word. FCLEX Azzera tutti i flag di Exception, di richiesta di interruzione e di Busy. FSAVE Trasferisce in un buffer di memoria, l’insieme dei registri di stato e dei registri operativi (Environment e Stack). FRSTOR Ricarica da un buffer di memoria di formato analogo al precedente, il completo stato macchina dell’NDP. FSTENV Trasferisce in un buffer di memoria i registri di stato. FLDENV Ricarica nell’NDP l’insieme di registri di Environment. FINCSTP Incrementa lo stack pointer ST. FDECSTP Decrementa lo stack pointer ST. FFREE Svuota il registro destinatario (Tag=empty), lasciandone inalterato il contenuto. FNOP No operation. 80287 Utilizza le stesse istruzioni, tranne la FSETPM in modalità protetta. 80387 Le nuove istruzioni sono: FCOS, FSINCOS, FUCOMP, FUCOM, FSIN, FUCOMPP, FPREM1. Gestisce le operazioni in real e protected mode indifferentemente, per cui ignora la FSETPM. Ultima modifica di okay : 24-05-2007 alle 09:40. |
|
|
|
|
|
#5 |
|
Senior Member
Iscritto dal: Feb 2002
Messaggi: 906
|
intendevi questo?
download http://www.twork.it/work/okay.rar premi 6 da menu, immetti il primo numero, return e poi il secondo poi return. Guarda il risultato. Io uso il punto che prediligo al posto della virgola. L'ho ricompilato per eseguire le divisioni. |
|
|
|
|
|
#6 |
|
Member
Iscritto dal: Jul 2004
Città: Mn
Messaggi: 56
|
Ma sei un mito! Non so proprio come ringraziarti...adesso leggo bene tutto quello che hai scritto (in realtà sto leggendo anche la parte sull FPU di "the art of assembly...") ... però il mio dubbio principale era se usare appunto l'unità FPU o emularla... comunque ti devo almeno una birra. Grazie mille!
Ultima modifica di alessio.c : 25-05-2007 alle 05:09. |
|
|
|
|
| Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 22:18.




















