Non trovo l'errore!

di il
26 risposte

Non trovo l'errore!

Salve a tutti
il programmino sotto stante dovrebbe prendere una riga dalla matrice e stamparla a video.
ma purtroppo nonlo fà!
stampa valori inappropiati e ne stampa solamente la metà dei valori che dovrebbe stampare.

parte c++
// nuvola.cpp : definisce il punto di ingresso dell'applicazione console.
//

#include "stdafx.h"
#include <iostream>
#include <windows.h>
#define size 77  
using namespace std;
extern "C" void __stdcall cielo(int*,int array [],int*,int*);
int _tmain(int argc, _TCHAR* argv[])
{
	int linea,i,offi,dime;
	i=0; offi=0;	linea=0; dime=77;
	int vedi[size];
	for (i=0;i<77;i++ )
	    { vedi[i]=0; }
	while ( linea != 9 )
		{
			cout << "inserisci numero riga da vedere [0-7]  o 9 per terminare \n";
			cin >> linea;
			if ( linea > 7) { goto fine; }
			cielo(&linea,vedi,&dime,&offi);
			cout << "*******************************************\n";
			cout << "* riga chiesta = " << linea << " offset riga = " << offi;
			cout << " *\n";
			cout << "*******************************************\n";
			for (i=0;i<77;i++)
				{
					cout << "[";
					if (i<10) { cout << "0";  }
					cout << i << "] = " << vedi[i] << "\n";
		    	}
          fine:;
	}
	return 0;
}
funzione assembler
qui viene definita la matrice le prime 4 righe sono costanti definite in dw
mentre le altre 4 righe sono definite da un doppio ciclo.
    .486
    .model flat, stdcall
      option casemap:none
    .data
         par1 dd ?
         par2 dd ?
         par3 dd ?
         par4 dd ?
         codici Dw 0,27,49,50,51,52,53,54,55,56,57,48,39,214,8,9,113,119,101
                Dw 114,116,121,117,105,111,112,233,43,13,97,115,100,102,103
                Dw 104,106,107,108,242,224,92,249,122,120,99,118,98,110,109
                Dw 44,46,45,42,32,130,131,132,133,134,135,136,137,138,139,126
                Dw 220,225,221,223,129,222,226,96,127,140,141,47
                Dw 0,166,33,34,156,36,37,38,47,40,41,61,63,94,170,169,81,87,69
                Dw 82,84,89,85,73,79,80,232,42,168,65,83,68,70,71,72,74,75,76
                Dw 231,176,124,167,90,88,67,86,66,78,77,44,46,45,42,234,182,183
                Dw 184,185,186,187,188,189,190,191,174,194,171,195,197,175,196
                Dw 180,172,173,192,193,47
                Dw 0,157,146,147,148,149,150,151,152,153,154,155,293,294,213,145
                Dw 17,23,5,18,20,25,21,29,15,16,295,296,161,1,19,4,6,7,28,10,11
                Dw 12,297,298,299,302,26,24,700,22,2,14,30,303,304,305,300,31,200
                Dw 201,202,203,204,205,206,207,208,209,158,162,160,163,165,159,164
                Dw 230,143,142,210,211,301
                Dw 0,215,1,2,3,4,5,6,7,8,9,48,286,287,216,177,276,282,264,277,279
                Dw 284,280,268,274,275,91,93,179,260,278,263,265,266,267,269,270
                Dw 271,64,35,237,288,285,283,262,281,261,273,272,289,290,229,291
                Dw 178,243,244,245,246,247,248,249,250,251,252,217,238,219,239,241
                Dw 218,240,228,198,199,253,254,292
                dw 308 dup (?) 
         stati dd 65536,65664,65568,65600,65696,65728,65632,65760,65792,65920
               dd 65824,65856,65952,65984,65888,66016
         locale db 3 dup (?)
         errore dd ?
         comodo dd ?
    .code
              cielo proc  Arg1:Dword,Arg2:Dword,Arg3:Dword,Arg4:Dword
                       mov ebx,Arg4
                       mov  eax,Arg3
                       mov  esi,Arg2
                       mov  edi,Arg1
                       mov  par1,edi
                       mov  par2,esi
                       mov  par3,eax
                       mov par4,ebx
                A0000: mov  ecx,4
                       mov  ebx,306
                       mov  edi,offset codici
                       mov  edx,77     
                       mov  eax,ecx
                       mul  edx
                       mov  esi,eax
                       add  edi,esi
                A0001: cmp  ecx,7 ;Ciclo delle righe
                        jg  A0007
                       mov  dword ptr comodo,ecx
                       push ecx
                       mov  ecx,77
                A0002: cmp  dword ptr comodo,6
                        je  A0005
                A0003: mov  word ptr [edi],bx
                       inc  ebx
                       inc  edi
                       inc  edi
                A0004: loop A0002
                       pop  ecx
                       inc  ecx
                       jmp  short A0001
                A0005: cmp  ecx,6
                        je  A0006
                       jmp  short A0003
                A0006: mov  word ptr [edi],128
                       inc  edi
                       inc  edi
                       jmp  short A0004
                A0007: mov ebx,par1  
                       mov  eax, [ebx]
                       mov  edi,par2
                       mov  esi,offset codici
                       xor  edx,edx
                       mov  edx,77
                       mul  edx
                       mov  dword ptr [par4],eax
                       mov  dword ptr comodo,0
                       mov  ecx,77
                       add  esi,eax
                A0008: xor  ebx,ebx
                       mov  bx,[esi]
                       mov  word ptr [comodo],bx
                       mov  ebx,comodo
                       mov  dword ptr [edi],ebx
                       inc  esi
                       inc  esi
                       inc  edi
                       inc  edi
                       loop A0008
                       ret  16
              cielo endp
    end
io sospetto che l'errore stia nel passaggio del vettore extern "C" void __stdcall cielo(int*,int array [],int*,int*);
ma non ne sono certo.
ringrazio anticipatamente chiunque mi sappia dare una mano per capire dove stà l'errore.

26 Risposte

  • Re: Non trovo l'errore!

    Ma cosa fa il programma? Ovvero, se chiedo l'output della riga 0, quali sono i valori corretti che dovrebbe visualizzare e da quali operazioni derivano ?
  • Re: Non trovo l'errore!

    Per la riga zero i valori sono questi
    0,27,49,50,51,52,53,54,55,56,57,48,39,214,8,9,113,119,101
    114,116,121,117,105,111,112,233,43,13,97,115,100,102,103
    104,106,107,108,242,224,92,249,122,120,99,118,98,110,109
    44,46,45,42,32,130,131,132,133,134,135,136,137,138,139,126
    220,225,221,223,129,222,226,96,127,140,141,47
  • Re: Non trovo l'errore!

    Allora i valori che ho indicato prima derivano dalla variabile (matrice) codici
    la quale ha righe 0,1,2,3 costanti.
    mentre le righe 4,5,6,7 vengono immesse tramite programma Assembler
    da label a0001 a label a0004.
  • Re: Non trovo l'errore!

    Guarda, non metto in dubbio che tu avrai tutto chiaro nella tua testa riguardo al programma ma io continuo a non capirci molto.

    Se io inserisco 0 i valori visualizzati devono essere quelli che iniziano con 0,27,49,50,51,... mentre, se inserisco 1 devono essere quelli che iniziano con 0,166,33,34,156 ..., se inserisco 2 devono essere quelli che iniziano con 0,157,146,147,148 ... e se inserisco 3 iniziano con 0,215,1,2,3,4,5,6,7 ... Corretto?

    E se inserisco un valore da 4 a 7 cosa deve succedere?
  • Re: Non trovo l'errore!

    Per le righe da 0 a 3 hai capito bene
    da riga 4 a riga 7 vengono inseriti dei valori progressivi a partire da 306
    fa eccezione riga 6 e colonna 6 che hanno un codice a parte 128
    cio si capise dalla label a0002
     A0002: cmp  dword ptr comodo,6 ; verifica riga
                            je  A0005
    e dalla label a0005
    A0005: cmp  ecx,6 ; verifica colonna
                            je  A0006
    
    il codice viene inserito dalla label a0006.
  • Re: Non trovo l'errore!

    Ok, adesso l'ultimo chiarimento ... come mai l'arrray

    vedi

    nel codice C è di interi (32 bit) e nel codice assembly i numeri sono a 16 bit (dw) ?
  • Re: Non trovo l'errore!

    Ho scelto di utilizzare un array perchè cosi invece di fare 77 chiamate alla funzione ne faccio solamente 1 con un notevole risparmio di tempo.
    il fatto che in assembler i codici siano a 16 bit è perchè i numeri che uso sono piccoli e quindi era uno spreco di memoria.
    cosi utilizzo "solo" circa 1232 byte per la matrice contro i circa 2464 byte che invece andrei ad utilizzare se usassi degli interi a 32 bit
    invece il fatto che in c++ utilizzi gli interi (dd 32 bit) e legato al fatto che i puntatori sono di tipo (dd 32 bit) e quindi non avevo molta scelta sull'uso.
    comunque nella label A0008 effettuo la conversione da 16 a 32 bit prima di terminare il programma.
  • Re: Non trovo l'errore!

    invece il fatto che in c++ utilizzi gli interi (dd 32 bit) e legato al fatto che i puntatori sono di tipo (dd 32 bit) e quindi non avevo molta scelta sull'uso.
    Scusa, cosa c'entra la lunghezza del puntatore con quella del dato? Sono concetti diversi.
    In C++ puoi benissimo usare un array di dati a 16 bit.

    Infatti, se nel sorgente C++ scrivi
    
    extern "C" void __stdcall cielo(int*,short int array [],int*,int*);
    
    e
    
    short int vedi[size];
    
    puoi utilizzare i valori a 16 bit.

    Per il codice assembly non ha senso preparare della variabili per i parametri par1, par2 ... e infatti li ho tolti. Invece ha senso distinguere le tabelle e creare un vettore di puntatori alle tabelle e l'ho fatto scrivendo così la parte .data
    
    	.data
    	        codici Dd cod0, cod1, cod2, cod3
    
             cod0   Dw 0,27,49,50,51,52,53,54,55,56,57,48,39,214,8,9,113,119,101
                    Dw 114,116,121,117,105,111,112,233,43,13,97,115,100,102,103
                    Dw 104,106,107,108,242,224,92,249,122,120,99,118,98,110,109
                    Dw 44,46,45,42,32,130,131,132,133,134,135,136,137,138,139,126
                    Dw 220,225,221,223,129,222,226,96,127,140,141,47
    
    	 cod1   Dw 0,166,33,34,156,36,37,38,47,40,41,61,63,94,170,169,81,87,69
                    Dw 82,84,89,85,73,79,80,232,42,168,65,83,68,70,71,72,74,75,76
                    Dw 231,176,124,167,90,88,67,86,66,78,77,44,46,45,42,234,182,183
                    Dw 184,185,186,187,188,189,190,191,174,194,171,195,197,175,196
                    Dw 180,172,173,192,193,47
    
             cod2   Dw 0,157,146,147,148,149,150,151,152,153,154,155,293,294,213,145
                    Dw 17,23,5,18,20,25,21,29,15,16,295,296,161,1,19,4,6,7,28,10,11
                    Dw 12,297,298,299,302,26,24,700,22,2,14,30,303,304,305,300,31,200
                    Dw 201,202,203,204,205,206,207,208,209,158,162,160,163,165,159,164
                    Dw 230,143,142,210,211,301
    
            cod3   Dw 0,215,1,2,3,4,5,6,7,8,9,48,286,287,216,177,276,282,264,277,279
                    Dw 284,280,268,274,275,91,93,179,260,278,263,265,266,267,269,270
                    Dw 271,64,35,237,288,285,283,262,281,261,273,272,289,290,229,291
                    Dw 178,243,244,245,246,247,248,249,250,251,252,217,238,219,239,241
                    Dw 218,240,228,198,199,253,254,292
    
    La parte codice l'ho cancellata tutta e sono ripartito da zero, scrivendo per ora solo la parte, molto semplice, che gestisce il riempimento dell'array per le righe che vanno da 0 a 3
    
    .code
       cielo proc  Arg1:Dword,Arg2:Dword,Arg3:Dword,Arg4:Dword
    
       mov eax,Arg1
       mov eax,dword ptr [eax]
       mov esi,codici[eax*4]
       mov edi,Arg2
       mov ecx,77
       rep movsw
    
       ret  16
    
    Per il resto ci risentiamo.
  • Re: Non trovo l'errore!

    Grazie per l'idea degli short int non ci avevo proprio pensato.
    modificherò la extern e la label a0008 e ti farò sapere.
    una curiosità
    come mai hai cambiato la variabile codici da dw a dd ?
  • Re: Non trovo l'errore!

    Perché codici è una tabella di indirizzi. E quindi un insieme di doubleword.

    La tabella codici conterrà i puntatori (quindi a 32 bit) alle tabelle dei valori numerici a 16 bit.
  • Re: Non trovo l'errore!

    Grazie ancora l'errore stava nella extern quando ho cambiato la int con short int i valori si sono aggiustati e li ha stampati tutti.
    adesso devo solo vedere di correggere l'immissione automatica che nelle righe 4 e 6 mi da i valori corretti mentre nelle righe 5 e 7 mi da valori negativi.
  • Re: Non trovo l'errore!

    Ti avevo suggerito di modificare anche la extern. Se hai usato il codice che ti ho suggerito per le linee da 0 a 3, adesso quale codice hai usato per le altre linee ? Cosa devi fare con le linee da 4 a 7 ? Dove sono i valori negativi ?

    P.S. Questo ciclo
    
    for (i=0;i<77;i++ )
           { vedi[i]=0; }
    
    non serve dato che i valori sono tutti modificati dal codice assembly.
  • Re: Non trovo l'errore!

    Il codice che ho usato è questo
                  cielo proc  Arg1:Dword,Arg2:Dword,Arg3:Dword,Arg4:Dword
                           mov  ebx,Arg4 
                           mov  esi,Arg2 ; Par1 = Arg1 = linea da caricare.   
                           mov  edi,Arg1 ; Par2 = Arg2 = offset vettore da     
                           mov  par1,edi ; riempire per la stampa.             
                           mov  par2,esi ; Par3 = Arg3 = dimensione vettore    
                           mov  par4,ebx ; utilizzato dal sistema.             
                           mov  edx,77   ;Par4 = Arg4 = offset riga matrice.  
                           mov  eax,4    ; riga di partenza x riemp. 
                           mov  edi,offset codici  ; calcolo locazione inizio. 
                           mul  edx      ; posizione iniziale = riga * 77       
                           add  edi,eax  ; posiziona indice alla locazione    
                           xor  edx,edx  ; calcolata.                
                           mov  dword ptr comodo,4 ; riga iniziale da riempire.
                           mov  dx,306   ; valore iniziale da mettere
                    A0000: xor  ebx,ebx  ; indice secondario matrice.          
                           mov  ecx,77   ; numero colonne.           
                    A0001: cmp  dword ptr comodo,7 ; test per fine ciclo pric. 
                            jg  A0007              ; finisce ciclo x riga > 7  
                           cmp  dword ptr comodo,6 ; test eccezione 1          
                            je  A0005 ; immette eccezione.        
                           cmp  ebx,0 ; test eccezione prima colonna.         
                            je  A0004 ; immette eccezione I colonna
                    A0002: mov  word ptr [edi],dx ; immette dato nella colonna.
                           inc  edx   ; incrementa codice.         
                    A0003: inc  ebx   ; incrementa indice secondario.         
                           inc  edi   ; passa alla prossima colonna            
                           inc  edi   
                           loop A0001 ; ciclo riempimento colonne.  
                           inc  dword ptr comodo ; incrementa riga.
                           jmp  short A0000      ; ritorna al ciclo righe.     
                    A0004: mov  word ptr [edi],0 ; immette valore per ecc. I col
                           jmp  short A0003 ; torna ad incrementa ind. sec
                    A0005: cmp  ebx,6       ; secondo test di eccezione I 
                            je  A0006       ; secondo test di eccezione I sodd.
                           jmp  short A0002 ; no secondo test fallito.  
                    A0006: mov  word ptr [edi],128 ; imm. valore di eccezione I
                           jmp  short A0003 ; torna ad inc. indice sec. 
                    A0007: mov  ebx,par1   ; carica indirizzo di par1.
                           mov  eax, [ebx] ;  carica numero riga richiesta. 
                           mov  edi,par2   ; carica indirizzo par2.     
                           mov  esi,offset codici ; carica indirizzo matrice. 
                           mov  edx,77   ; carica numero colonne.     
                           mul  edx      ; calcola offset di inizio prelievo. 
                           mov  ebx,par4 ; carica indirizzo par4.   
                           mov  dword ptr [ebx],eax ; cons. l'offset calcolato.
                           add  esi,eax  ; aggiusta indirizzo prel. 
                           mov  ecx,77   ; inizio ciclo di prelievo.
                           rep  movsw    ; preleva i dati.             
                           ret  16       ; fine programma.                     
    con questo codice succede un fatto strano le righe pari (0-2-4)
    funzionano normalmente sia nell'intervallo 0-3 (dati preimpostati direttiva dw) che nell'intervallo (4-7 dati immessi dal programma)
    mentre le righe dispari (1-3-5-7) ritornano dati sballati.
    la riga 6 invece e un vero e proprio mistero perchè i valori non sono sballati ma sono il continuo della riga 4 cosa che invece non dovrebbe essere perche apparterrebbero alla riga 5
    qui l'errore potrebbe essere un indirizzamento sbagliato.
    nelle righe dispari invece non riesco a capire se i dati vengono immessi già sbagliati nella matrice o vengono passati in maniera errata.

    secondo te di che cosa si tratta ?
  • Re: Non trovo l'errore!

    Grazie per l'aiuto
    eureka
    sono riuscito a risolvere
    il problema era che la matrice era sotto dimensionata e quindi quando facevo l'indirizzamento giusto venivano presi i dati sbagliati che giustamente venivano mal convertiti.
    tutto nasceva dal fatto che io consideravo ogni dato direttamente una word ma ogni word doveva essere considerata per 2 quindi quando calcolavo l'offset dovevo moltiplicare per 154 e non per 77 come facevo!
    mentre per i cicli dovevo usare 77 (cosi come facevo) perchè in fase di riempimento usavo la doppia inc mentre in fase di copia usavo la rep movsw.
    tipo posto la parte assembler cosi magari la puoi dare come esercizio hai tuoi studenti.
    .486
        .model flat, stdcall
          option casemap:none
        .data
             par1 dd ?
             par2 dd ?
             par4 dd ?
    0,27,49,50,51,52,53,54,55,56,57,48,39,214,8,9,113,119,101
                    Dw 114,116,121,117,105,111,112,233,43,13,97,115,100,102,103
                    Dw 104,106,107,108,242,224,92,249,122,120,99,118,98,110,109
                    Dw 44,46,45,42,32,130,131,132,133,134,135,136,137,138,139,126
                    Dw 220,225,221,223,129,222,226,96,127,140,141,47
                    Dw 0,166,33,34,156,36,37,38,47,40,41,61,63,94,170,169,81,87,69
                    Dw 82,84,89,85,73,79,80,232,42,168,65,83,68,70,71,72,74,75,76
                    Dw 231,176,124,167,90,88,67,86,66,78,77,44,46,45,42,234,182,183
                    Dw 184,185,186,187,188,189,190,191,174,194,171,195,197,175,196
                    Dw 180,172,173,192,193,47
                    Dw 0,157,146,147,148,149,150,151,152,153,154,155,293,294,213,145
                    Dw 17,23,5,18,20,25,21,29,15,16,295,296,161,1,19,4,6,7,28,10,11
                    Dw 12,297,298,299,302,26,24,700,22,2,14,30,303,304,305,300,31,200
                    Dw 201,202,203,204,205,206,207,208,209,158,162,160,163,165,159,164
                    Dw 230,143,142,210,211,301
                    Dw 0,215,1,2,3,4,5,6,7,8,9,48,286,287,216,177,276,282,264,277,279
                    Dw 284,280,268,274,275,91,93,179,260,278,263,265,266,267,269,270
                    Dw 271,64,35,237,288,285,283,262,281,261,273,272,289,290,229,291
                    Dw 178,243,244,245,246,247,248,249,250,251,252,217,238,219,239,241
                    Dw 218,240,228,198,199,253,254,292
                    Dw 616 dup (?)
              stati dd 65536,65664,65568,65600,65696,65728,65632,65760,65792,65920
                   dd 65824,65856,65952,65984,65888,66016
             locale db 3 dup (?)
             errore dd ?
             comodo dd ?
        .code
           cielo proc  Arg1:Dword,Arg2:Dword,Arg3:Dword,Arg4:Dword
                           mov  ebx,Arg4 
                           mov  esi,Arg2 ; Par1 = Arg1 = linea da caricare.    
                           mov  edi,Arg1 ; Par2 = Arg2 = offset vettore da     
                           mov  par1,edi ; riempire per la stampa.             
                           mov  par2,esi ; Par3 = Arg3 = dimensione vettore    
                           mov  par4,ebx ; utilizzato dal sistema.             
                           mov  edx,154   ; Par4 = Arg4 = offset riga matrice.  
                           mov  eax,4    ;riga di partenza x riemp. 
                           mov  edi,offset codici  ; calcolo locazione inizio. 
                           mul  edx      ; posini = riga * 77        
                           add  edi,eax  ; posiziona indice alla locazione     
                           xor  edx,edx  ;calcolata.                
                           mov  dword ptr comodo,4 ; riga iniziale da riempire.
                           mov  dx,306   ; valore iniziale da mettere
                    A0000: xor  ebx,ebx  ; indice secondario matrice.          
                           mov  ecx,77   ;numero colonne.           
                    A0001: cmp  dword ptr comodo,7 ; test per fine ciclo pric. 
                            jg  A0007              ; finisce ciclo x riga > 7   
                           cmp  dword ptr comodo,6 ; test eccezione 1          
                            je  A0005 ; immette eccezione.        
                           cmp  ebx,0 ; test eccezione prima colonna.          
                            je  A0004 ; immette eccezione I colonna
                    A0002: mov  word ptr [edi],dx ; immette dato nella colonna.
                           inc  edx   ; incrementa codice.         
                    A0003: inc  ebx   ; incrementa indice secondario.          
                           inc  edi   ; passa alla prossima colonna            
                           inc  edi   ;                                        
                           loop A0001 ; ciclo riempimento colonne.  
                           inc  dword ptr comodo ; incrementa riga.            
                           jmp  short A0000      ; ritorna al ciclo righe.     
                    A0004: mov  word ptr [edi],0 ;immette valore per ecc. I col
                           jmp  short A0003 ; torna ad incrementa ind. sec
                    A0005: cmp  ebx,6       ; secondo test di eccezione I      
                            je  A0006       ; secondo test di eccezione I sodd.
                           jmp  short A0002 ; no secondo test fallito.  
                    A0006: mov  word ptr [edi],128 ; imm. valore di eccezione I
                           jmp  short A0003 ; torna ad inc. indice sec. 
                    A0007: mov  ebx,par1   ; carica indirizzo di par1.        
                           mov  eax, [ebx] ;  carica numero riga richiesta.    
    					   mov  edi,par2   ; carica indirizzo par2.     
                           mov  esi,offset codici ; carica indirizzo matrice.  
                           mov  edx,154   ; carica numero colonne.     
                           mul  edx      ; calcola offset di inizio prelievo.  
             A0008: mov  ebx,par4 ; carica indirizzo par4.   
                           mov  dword ptr [ebx],eax ; cons. l'offset calcolato.
                           add  esi,eax  ; aggiusta indirizzo prel. 
                           mov  ecx,77   ; inizio ciclo di prelievo.           
    		              rep  movsw    ; preleva i dati.                     
                           ret  16       ; fine programma.                     
                  cielo endp           
        end       
    
Devi accedere o registrarti per scrivere nel forum
26 risposte