Gladior
Matricola
Offline
Posts: 87
|
 |
« Reply #330 on: 13-08-2012, 01:47:21 » |
|
Ho un dubbio riguardante il simulatore dell'istruzione INVOKEVIRTUAL Quando eseguiamo l'istruzione LDC_W OBJREF abbiamo i seguenti valori 0x13 e 0x15 dove quest'ultimo rappresenta il riferimento della constant pool che contiene objref il mio dubbio è questo objref contiene un valore 0xb22 che non riesco a capire come si calcola.
L'operando di INVOKEVIRTUAL, come pure quello di LDC_W, è uno spiazzamento (o indice, o offset, la terminologia è un po' varia al riguardo) rispetto all'indirizzo iniziale dell'area delle costanti. Quest'ultimo è il contenuto del registro CPP. Non riesco a capire come calcolare lo spiazzamento o meglio l'operando di LDC_W Objref nella constant pool è indicato l'offeset 0xb22 come viene calcolato questo spiazzamento?
|
|
|
Logged
|
|
|
|
Giuseppe Scollo
|
 |
« Reply #331 on: 13-08-2012, 18:07:06 » |
|
L'operando di INVOKEVIRTUAL, come pure quello di LDC_W, è uno spiazzamento (o indice, o offset, la terminologia è un po' varia al riguardo) rispetto all'indirizzo iniziale dell'area delle costanti. Quest'ultimo è il contenuto del registro CPP.
Non riesco a capire come calcolare lo spiazzamento o meglio l'operando di LDC_W Objref nella constant pool è indicato l'offeset 0xb22 come viene calcolato questo spiazzamento? Come si calcola dovrebbe essere chiaro dalla mia risposta precedente: l'indirizzo assoluto dell'oggetto nell'area delle costanti deve risultare quale somma del contenuto di CPP e dello spiazzamento. Noto l'indirizzo assoluto e il contenuto di CPP, lo spiazzamento si calcola dunque per differenza. Forse il suo dubbio deriva dalla questione del "chi" calcola questo indirizzo. Verosimilmente, non il programmatore IJVM, che userà un simbolo quale operando, bensì l'interprete o simulatore che sia. Quale simulatore usa?
|
|
|
Logged
|
|
|
|
|
Giuseppe Scollo
|
 |
« Reply #333 on: 14-08-2012, 07:06:17 » |
|
Ora capisco la fonte del suo dubbio, grazie. Premessa: l'autore della simulazione segnala un errore in questa, nella pagina di presentazione della simulazione, riguardante gli indirizzi di memoria. Per la precisione, l'errore riguarda solo gli indirizzi delle istruzioni, ovvero relativi all'area dei Metodi, usati per l'aggiornamento del PC (dovrebbero essere indirizzi di byte, non di parole da 4 byte). Con riferimento al suo dubbio, non ha ragione di sussistere: nella JVM, il valore di OBJREF è un riferimento (puntatore) all'oggetto contenente il metodo invocato e serve a determinare dinamicamente l'indirizzo del metodo. Nella IJVM non si fa uso di tale valore, poiché si impone (per semplicità) che tale oggetto sia lo stesso oggetto che contiene il metodo chiamante. Tuttavia, il passaggio di OBJREF quale primo parametro (parametro 0) nella pila viene mantenuto per compatibilità con la JVM. Dunque, nell'esempio in questione, il valore di OBJREF è una costante scelta un po' a casaccio, e non gioca alcun ruolo nell'effettiva esecuzione dell'istruzione di chiamata (come può constatare dalla simulazione stessa). L'analisi della simulazione sollecitata dal suo dubbio rivela però un altro erroruccio nella simulazione stessa: come può notare, durante l'esecuzione dell'istruzione di chiamata, precisamente al passo in cui si memorizza in pila il PC del chiamante, il valore di OBJREF nel pool delle costanti muta (diventando l'indirizzo di una delle istruzioni nel corpo del metodo chiamato); la strana mutazione dura fino al caricamento del primo parametro nel metodo chiamato (ILOAD J); al successivo caricamento (ILOAD K), OBJREF torna al suo valore precedente. Questo è chiaramente un errore, per il semplice fatto che una costante non muta (per definizione di costante), ma anche questo non ha alcuna influenza sul resto della simulazione.
|
|
|
Logged
|
|
|
|
Gladior
Matricola
Offline
Posts: 87
|
 |
« Reply #334 on: 14-08-2012, 16:15:34 » |
|
Quesito N°20 La traduzionein mic 1 dell'istruzione MAL IF(Z)gotoL1; else goto L2 deve assegnare a L2 un indirizzo nella metà bassa della memoria di controllo. Perchè
Sappiamo invece , che è L2 che deve essere più in basso di 256 word, prorpio perchè se il test su Z è positivo il bit i MPC sarà uno , altrimenti zero. quindi le alternative sono L2 se il test è negativo L1 se il test è positivo
|
|
|
Logged
|
|
|
|
Giuseppe Scollo
|
 |
« Reply #335 on: 14-08-2012, 21:55:30 » |
|
Quesito N°20 La traduzionein mic 1 dell'istruzione MAL IF(Z)gotoL1; else goto L2 deve assegnare a L2 un indirizzo nella metà bassa della memoria di controllo. Perchè
Sappiamo invece , che è L2 che deve essere più in basso di 256 word, prorpio perchè se il test su Z è positivo il bit i MPC sarà uno , altrimenti zero. quindi le alternative sono L2 se il test è negativo L1 se il test è positivo
La correzione è ok. Continuo a trovare inappropriato l'"invece ,", perché nel quesito non è enunciato il contrario, dunque "invece" di che?
|
|
|
Logged
|
|
|
|
Gladior
Matricola
Offline
Posts: 87
|
 |
« Reply #336 on: 18-08-2012, 12:43:23 » |
|
imul1 Z=TOS;if(Z) goto imul7 ; else goto imul2 //TEST DELL'INDICE , SE NULLO IL PRODOTTO VALE ZERO ALTRIMENTI... imul2 MAR=SP=SP-1;rd //LEGGE SECONDO OPERANDO DALLO STACK E DECREMENTA SP , ORA IL 2° OPERANDO E' IN MDR imul3 H=0 //AZZERA SOMMA PARZIALE imul4 H=H+MDR //INCREMENTA PRODOTTO PARZIALE imul5 TOS=TOS-1;if(Z) goto imul6 ; else goto imul4 //SE INDICE NON NULLO RIPETE SOMMA , ALTRIMENTI PRODOTTO FINITO imul6 MDR=TOS=H;wr;goto Main1 //PUSH SULLO STACK DEL RISULTATO , AGGIORNO TOS E SALTO ALLA MICROROUTINE DI FETCH imul7 MDR=0;wr;goto Main1 //SE TOS = 0 ALLORA PRODOTTO = 0 E SALTO ALA MICROROUTINE DI FETCH
L'istruzione IJVM (IMUL) è Interpretata nel seguente modo da mic-1
|
|
|
Logged
|
|
|
|
Gladior
Matricola
Offline
Posts: 87
|
 |
« Reply #337 on: 18-08-2012, 12:47:05 » |
|
IMPLEMENTATO CON ISTRUZIONI IJVM:
IJVM non ha istruzioni per la moltiplicazione, il che spiega perché il suo programma richieda ben più di 10 istruzioni. In linea di principio, non è una buona idea risolvere un problema diverso da quello proposto, perlomeno in sede di esame (si rischia di conseguire la valutazione 0 perché il problema proposto non è stato affrontato; in altra sede, naturalmente, è un esercizio legittimo e utile quanto qualsiasi altro). Se vuole usare la sintassi IJVM potenziata con una istruzione per la moltiplicazione, la cosa più ovvia da fare è dare a quest'ultima una sintassi simile a quella delle altre operazioni aritmetiche, quali IADD e ISUB. Dunque, ad es., la nuova istruzione IMUL (senza operandi) estrae i suoi due argomenti dalla cima dello stack, e al posto del secondo vi pone il risultato della loro moltiplicazione (che si troverà dunque in cima allo stack dopo l'esecuzione di IMUL). Un suggerimento per affrontare meglio il problema, disponendo dell'istruzione IMUL: definire il calcolo del fattoriale mediante un metodo ricorsivo (attenzione dunque al passaggio del parametro: deve avvenire per il tramite dello stack, prima dell'invocazione ricorsiva del metodo nel suo stesso corpo). imul1 Z=TOS;if(Z) goto imul7 ; else goto imul2 //TEST DELL'INDICE , SE NULLO IL PRODOTTO VALE ZERO ALTRIMENTI... imul2 MAR=SP=SP-1;rd //LEGGE SECONDO OPERANDO DALLO STACK E DECREMENTA SP , ORA IL 2° OPERANDO E' IN MDR imul3 H=0 //AZZERA SOMMA PARZIALE imul4 H=H+MDR //INCREMENTA PRODOTTO PARZIALE imul5 TOS=TOS-1;if(Z) goto imul6 ; else goto imul4 //SE INDICE NON NULLO RIPETE SOMMA , ALTRIMENTI PRODOTTO FINITO imul6 MDR=TOS=H;wr;goto Main1 //PUSH SULLO STACK DEL RISULTATO , AGGIORNO TOS E SALTO ALLA MICROROUTINE DI FETCH imul7 MDR=0;wr;goto Main1 //SE TOS = 0 ALLORA PRODOTTO = 0 E SALTO ALA MICROROUTINE DI FETCH L'istruzione IJVM (IMUL) è Interpretata nel seguente modo da mic-1
|
|
|
Logged
|
|
|
|
Gladior
Matricola
Offline
Posts: 87
|
 |
« Reply #338 on: 18-08-2012, 16:06:33 » |
|
Questo è un esercizio simile a quello che richiede di scrivere un metodo ricorsivo per il fattoriale. Ho svolto l'esercizio nel caso in cui non è richiesto un metodo ma un semplice codice IJVM che calcoli il fattoriale,nel caso specifico il programma risulta essere eccessivamente lungo? Ho fatto in modo che il valore del primo BIPUSH corrisponde al fattoriale da calcolare. Il programma funziona il mio dubbio è nel caso in cui mi dovrebbe capitare un esercizio del genere nel compito sarebbe valutato eccesivamente lungo? Potrebbe darmi qualche dritta per ridurre il numero di istruzioni ovviamente nel caso specifico ? Magari prossimamente postero il metodo ricorsivo utilizzando l'istruzione IMUL.
.main .var fatt somma cont FATTCONT .end-var BIPUSH 4 ISTORE fatt ILOAD fatt IFEQ zero ILOAD fatt BIPUSH 1 ISUB ISTORE FATTCONT ILOAD fatt ISTORE cont ILOAD cont BIPUSH 2 ISUB ISTORE cont ILOAD fatt ISTORE somma fattoriale: ILOAD cont IFEQ CONTA ILOAD fatt ILOAD somma IADD ISTORE fatt ILOAD cont BIPUSH 1 ISUB ISTORE cont GOTO fattoriale CONTA: ILOAD FATTCONT BIPUSH 1 ISUB ISTORE FATTCONT ILOAD FATTCONT ISTORE cont ILOAD fatt ISTORE somma BIPUSH 0 ISTORE fatt ILOAD FATTCONT IFEQ RISUL GOTO fattoriale zero: BIPUSH 1 ISTORE fatt GOTO FINE RISUL: ILOAD somma ISTORE fatt FINE: NOP .end-main
|
|
|
Logged
|
|
|
|
Gladior
Matricola
Offline
Posts: 87
|
 |
« Reply #339 on: 20-08-2012, 20:58:27 » |
|
metodo che cacola il fattoriale é corretto? .constant OBJREF 0x10 .end-constant .main .var fatt risul .end-var LDCW OBJREF IN ISTORE fatt ILOAD fatt INVOKEVIRTUAL fattoriale ISTORE risul ILOAD risul OUT HALT .end-main
.method fattoriale(fatt1) .var cont somp somma cont1 .end-var ILOAD fatt1 ISTORE cont1 ILOAD fatt1 BIPUSH 1 ISUB ISTORE cont ILOAD cont1 BIPUSH 2 ISUB ISTORE cont1 ciclo: ILOAD cont IFEQ ciclo2 ILOAD fatt1 ILOAD somp IADD ISTORE somp ILOAD cont BIPUSH 1 ISUB ISTORE cont GOTO ciclo ciclo2: ILOAD cont1 ISTORE cont ILOAD cont1 BIPUSH 1 ISUB ISTORE cont1 ILOAD somp ISTORE fatt1 BIPUSH 0 ISTORE somp ILOAD cont1 IFEQ risul GOTO ciclo risul: ILOAD fatt1 IRETURN .end-method
|
|
« Last Edit: 20-08-2012, 21:00:44 by Gladior »
|
Logged
|
|
|
|
Gladior
Matricola
Offline
Posts: 87
|
 |
« Reply #340 on: 29-08-2012, 09:45:32 » |
|
Esercizio : metodo ricorsivo fattoriale
.main .var fatt risul .end-var BIPUSH 5 ISTORE fatt LDCW OBJREF ILOAD fatt INVOKEVIRTUAL fatt ISTORE risul ILOAD risul OUT .end-main
.method fatt(a) .var fatt .end-var LDCW OBJREF ILOAD a BIPUSH 1 IFICMPEQ base ILOAD a BIPUSH 1 ISUB INVOKEVIRTUAL fatt ISTORE fatt ILOAD a ILOAD fatt IMUL ireturn base: BIPUSH 1 IRETURN .end-method
|
|
|
Logged
|
|
|
|
Giuseppe Scollo
|
 |
« Reply #341 on: 04-09-2012, 23:11:01 » |
|
imul1 Z=TOS;if(Z) goto imul7 ; else goto imul2 //TEST DELL'INDICE , SE NULLO IL PRODOTTO VALE ZERO ALTRIMENTI...
(...) imul7 MDR=0;wr;goto Main1 //SE TOS = 0 ALLORA PRODOTTO = 0 E SALTO ALA MICROROUTINE DI FETCH
La prima istruzione è erronea, perché se l'operando in cima allo stack è nullo, il prodotto, anch'esso nullo, dovrebbe essere scritto quale valore di ritorno nello stack, sovrascrivendo il secondo parametro. Invece, con il salto a imul7 si lancia un'operazione di scrittura in memoria caricando con 0 il registro MDR, ma senza aver previamente caricato il registro MAR: dove va a finire lo 0 in questione? Chissà...
|
|
|
Logged
|
|
|
|
Giuseppe Scollo
|
 |
« Reply #342 on: 04-09-2012, 23:24:31 » |
|
Questo è un esercizio simile a quello che richiede di scrivere un metodo ricorsivo per il fattoriale. Ho svolto l'esercizio nel caso in cui non è richiesto un metodo ma un semplice codice IJVM che calcoli il fattoriale,nel caso specifico il programma risulta essere eccessivamente lungo?
È evidente che il programma è molto più lungo del necessario. Ho fatto in modo che il valore del primo BIPUSH corrisponde al fattoriale da calcolare. Il programma funziona il mio dubbio è nel caso in cui mi dovrebbe capitare un esercizio del genere nel compito sarebbe valutato eccesivamente lungo? Potrebbe darmi qualche dritta per ridurre il numero di istruzioni ovviamente nel caso specifico ? Magari prossimamente postero il metodo ricorsivo utilizzando l'istruzione IMUL.
Ho visto che ne ha prodotto due versioni, suppongo che la seconda rimpiazzi la prima, guarderò pertanto solo quest'ultima. Quanto alla presente soluzione, non ricorsiva, ho la netta sensazione che la fonte di prolissità del programma stia nell'idea che l'uso dell'istruzione IMUL sia lecito solo nella soluzione ricorsiva. Non è così: si può produrre un calcolo non ricorsivo del fattoriale mediante un ciclo di moltiplicazioni, in una macchina che disponga della moltiplicazione, più o meno come si calcola il prodotto mediante un ciclo di addizioni in una macchina che non disponga dell'istruzione di moltiplicazione. Va bene come dritta?
|
|
|
Logged
|
|
|
|
Giuseppe Scollo
|
 |
« Reply #343 on: 04-09-2012, 23:43:48 » |
|
Esercizio : metodo ricorsivo fattoriale
.main .var fatt risul .end-var BIPUSH 5 ISTORE fatt LDCW OBJREF ILOAD fatt INVOKEVIRTUAL fatt ISTORE risul ILOAD risul OUT .end-main
.method fatt(a) .var fatt .end-var LDCW OBJREF ILOAD a BIPUSH 1 IFICMPEQ base ILOAD a BIPUSH 1 ISUB INVOKEVIRTUAL fatt ISTORE fatt ILOAD a ILOAD fatt IMUL ireturn base: BIPUSH 1 IRETURN .end-method
Mi sembra sostanzialmente corretto, a meno di due correzioni, una di forma, l'altra di sostanza. Forma: la sintassi IJVM prevede il codice operativo simbolico LDC_W, non LDCW. Sostanza: l'istruzione LDC_W OBJREF nel metodo fatt(a) dovrebbe essere spostata tre righe più avanti: va infatti eseguita solo se subito dopo si carica lo stack con i parametri e quindi si invoca un metodo; ora, nel caso in cui il test IFICMPEQ abbia esito positivo, si salta a base senza invocare alcun metodo, e dunque aver caricato anche in questo caso OBJREF nello stack produce un'alterazione erronea del contenuto di SP.
|
|
|
Logged
|
|
|
|
Gladior
Matricola
Offline
Posts: 87
|
 |
« Reply #344 on: 05-09-2012, 17:44:26 » |
|
imul1 Z=TOS;if(Z) goto imul7 ; else goto imul2 //TEST DELL'INDICE , SE NULLO IL PRODOTTO VALE ZERO ALTRIMENTI...
(...) imul7 MDR=0;wr;goto Main1 //SE TOS = 0 ALLORA PRODOTTO = 0 E SALTO ALA MICROROUTINE DI FETCH
La prima istruzione è erronea, perché se l'operando in cima allo stack è nullo, il prodotto, anch'esso nullo, dovrebbe essere scritto quale valore di ritorno nello stack, sovrascrivendo il secondo parametro. Invece, con il salto a imul7 si lancia un'operazione di scrittura in memoria caricando con 0 il registro MDR, ma senza aver previamente caricato il registro MAR: dove va a finire lo 0 in questione? Chissà... imul1 MAR=SP=SP-1;rd imul2 H=0//AZZERA SOMMA PARZIALE imul3 H=H+MDR//INCREMENTA PRODOTTO PARZIALE imul4 TOS=TOS-1;if(Z) goto imul5 ; else goto imul3 imul5 MDR=TOS=H;wr;goto Main1//PUSH SULLO STACK DEL RISULTATO , AGGIORNO TOS E SALTO ALLA MICROROUTINE DI FETCH
|
|
|
Logged
|
|
|
|
|