|
|
|
![]() |
|
Strumenti |
![]() |
#1 |
Member
Iscritto dal: Jun 2006
Messaggi: 86
|
[ASM] Strano non è vero?
Ciao ragazzi ho consegnato online il materiale e il professore una volta controllato il codice ASM del mio elaborato dice:
Se imposta i dati di input secondo il caso di prova riportato dal correttore, ossia unsigned int Point = ( (-1000)<<16 | ((1000)&0xFFFF) ); unsigned int PointSet[]={ (0<<16) | (0)&0xFFFF, (1000<<16) | (1000)&0xFFFF, (-1000<<16) | (-1000)&0xFFFF, ((-999)<<16) | (999)&0xFFFF, ((-1000)<<16) | (200)&0xFFFF }; noterà che il suo programma restituisce l'indice 1 (il punto 1000,1000), mentre il punto più vicino è quello di indice 3 (999,-999). Suggerisco di eseguire passo a passo con il debugger il programma in modo da trovare l'errore. ECCO IL MIO ELABORATO 2: #include <stdio.h> void main() { unsigned int Point = (5<<16) | (3)&0xFFFF; //il punto unsigned int PointSet[] = { (10<<16) | (3)&0xFFFF, (4<<16) | (2)&0xFFFF, (5<<16) | (20)&0xFFFF}; //insieme int n = sizeof(PointSet)/sizeof(PointSet[0]); // numero punti dell'insieme int index; //risultato: indice del punto più vicino a Point __asm { MOV ECX,n //Inizializza il registro ECX con il valore del numero dei punti n MOV EDX,1 //Carica il valore 1 nel registro EDX per il confronto con il valore n CMP EDX,ECX //Confronta 1 con il valore n JE Fine //Salta a Fine se n=1 (si confronto un solo punto) Ciclo1: MOV EAX,PointSet[ECX*4-4] // Inizia il ciclo che carica ogni elemento del vettore per confrontarlo con il punto dato in termini di distanza PUSH EAX // Salvaguarda il contenuto di EAX (coordinate del punto corrente) nello stack per poter operare su EAX senza perdere il valore precedente MOV EBX,Point[0] //Carica in EBX il punto dato verso il quale determinare la distanza PUSH EBX //Salvaguarda il contenuto di EBX nello stack come sopra AND EAX,0000FFFFh //Isola il valore di x del punto corrente dal suo valore y nel registro EAX TEST AH,10000000b //Verifica se x del punto corrente è negativo JNZ NegativoxVettore //Se x è negativo salta a NegativoxVettore dove provvede ad estendere il valore 1 in tutti i 16 bit più significativi Coordinatay: AND EBX,0000FFFFh //Isola il valore di x del punto dato dal suo valore y nel registro EBX TEST BH,10000000b //Verifica se x del punto dato è negativo JNZ NegativoxPunto //Se x è negativo salta a NegativoxPunto dove provvede ad estendere a 1 tutti i 16 bit più significativi Prosegui1: SUB EAX,EBX //Effettua la sottrazione tra le coordinate x del punto dato e del punto corrente MUL EAX //Eleva al quadrato il riultato della sottrazione precedente facendo la moltiplicazione per se stesso POP EBX //Estrae dallo stack e inserisce nel registro EBX nuovamente le coordinate del punto corrente SHR EBX,16 //Sposta i primi 16 bit più significativi contenenti y del punto corrente nei 16 bit meno significativi TEST BH,10000000b //Verifica se y del punto corrente è negativo JNZ NegativoyVettore //Se y è negativo salta a NegativoyVettore dove provvede ad estendere a 1 tutti i 16 bit più significativi Prosegui2: POP EDX //Estrae dallo stack e inserisce nel registro EDX nuovamente le coordinate del punto dato SHR EDX,16 //Sposta i primi 16 bit più significativi contenenti y del punto dato nei 16 bit meno significativi TEST DH,10000000b //Verifica se y del punto dato è negativo JNZ NegativoyPunto //Se y è negativo salta a NegativoyPunto dove provvede ad estendere a 1 tutti i 16 bit più significativi Prosegui3: SUB EDX,EBX //Effettua la sottrazione tra le coordinate y del punto dato e del punto corrente MOV EBX,EAX //Salvaguarda il contenuto di EAX nel registro EBX MOV EAX,EDX //Carica in EAX la differenza per predisporla alla moltiplicazione per se stessa MUL EAX //Eleva al quadrato la differenza fra le y del punto corrente e del punto dato facendo la moltiplicazione per se stessa ADD EAX,EBX //Somma i quadrati delle differenze tra le x e le y del punto dato e del punto corrente che rappresenta la distanza al quadrato PUSH EAX //Salvaguarda nello stack la distanza al quadrato corrente da utilizzare per individuare quella minore LOOP Ciclo1 //Gestione del Ciclo che ripete tutte le operazioni precedenti per ogni punto JMP VersoFine //Salta a fine una volta terminato il ciclo e calcolati tutti i quadrati delle distanze salvaguardati nello stack NegativoxVettore: OR EAX,11111111111111110000000000000000b //Imposta a 1 i 16 bit più significativi della componente x del punto corrente JMP Coordinatay //Ritorna all'interno del Ciclo1 NegativoxPunto: OR EBX,11111111111111110000000000000000b //Imposta a 1 i 16 bit più significativi della componente x del punto dato JMP Prosegui1 //Ritorna all'interno del Ciclo1 NegativoyVettore: OR EBX,11111111111111110000000000000000b //Imposta a 1 i 16 bit più significativi della componente y del punto corrente JMP Prosegui2 //Ritorna all'interno del Ciclo1 NegativoyPunto: OR EDX,11111111111111110000000000000000b //Imposta a 1 i 16 bit più significativi della componente y del punto dato JMP Prosegui3 //Ritorna all'interno del Ciclo1 VersoFine: MOV ECX,n //Carica nel registro ECX la dimensione n del vettore DEC ECX //Decrementa di 1 il valore del registro ECX MOV EDX,1 //Carica il valore 1 nel registro EDX (qui utilizzato per identificare l'indice della distanza al quadrato più piccolo) POP EAX //Inizia l'estrazione delle distanza del quadrato per il loro conronto Ciclo2: POP EBX //Inizio del ciclo di confronto CMP EAX,EBX //Confronto tra le distanze corenti JB Ritorno //Salta se la differenza delle distanze al quadrato è negativa MOV EAX,EBX //Altrimenti scambia le due distanze in modo da mettere quella più piccola sempre in EAX INC EDX //Calcola l'indice della distanza più piccola finora individuata e salvata in EAX Ritorno: LOOP Ciclo2 //Ritorna al Ciclo2 per terminare i confronti delle distanze al quadrato Fine: DEC EDX //Decrementa di 1 il valore del registro EDX per adeguarsi all'indice del vettore MOV index,EDX //Carica l'indice trovato nella variabile index per stamparla a video } // Stampa su video printf("Il punto piu' vicino a (%d,%d) e' (%d,%d) [indice=%d]\n",(short int)(Point&0xFFFF),(short int)(Point>>16),(short int)(PointSet[index]&0xFFFF),(short int)(PointSet[index]>>16),index); } Provate con altri punti anche quelli negativi e il programma funziona come deve. Mettendo il caso che dice il prof mi dà l'indice sbagliato. Perchè? ![]() ![]() |
![]() |
![]() |
![]() |
#2 |
Senior Member
Iscritto dal: Nov 2005
Città: TO
Messaggi: 5206
|
Scusa .... ma perché devi fare tutto 'sto macello per calcolare la distanza tra 2 punti???
Se devi fare una estensione di segno da 16 a 32 bit, ci sono già delle istruzioni apposite come la CWDE (che però fa solo AX --> EAX) oppure la più generica MOVSX. EDIT: Se programmi in assembly è meglio se tieni a portata di mano i manuali ufficiali della Intel che trovi <qui>. Queste dovrebbero essere le tue bibbie. ![]()
__________________
Andrea, SCJP 5 (91%) - SCWCD 5 (94%) Ultima modifica di andbin : 26-06-2006 alle 16:25. |
![]() |
![]() |
![]() |
#3 |
Senior Member
Iscritto dal: Nov 2005
Città: TO
Messaggi: 5206
|
Aggiungo un'altra cosa importante (che mi è venuta in mente solo oggi
![]() Il risultato delle sottrazioni x2-x1 e y2-y1 è un valore con segno (può essere, giustamente, anche negativo). In questa situazione NON devi usare la MUL ma devi usare la IMUL. Questo perché la MUL opera su valori senza segno. Quindi un valore di FFFFFC18h (-1000 in complemento due su 32 bit) verrebbe visto come 4294966296 e il risultato della moltiplicazione ... beh, prova ad immaginarlo! ![]() La IMUL invece opera su valori con segno.
__________________
Andrea, SCJP 5 (91%) - SCWCD 5 (94%) |
![]() |
![]() |
![]() |
#4 |
Member
Iscritto dal: Jun 2006
Messaggi: 86
|
uhm...
Ciao Andrea ok grazie del consiglio.
Ci sentiamo oggi pomeriggio magari in chat che ho un sacco di domande da porti. Mi dici quando sei libero in chat? Grazie ancora a dopo! ![]() |
![]() |
![]() |
![]() |
Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 13:48.