Non riesco a capire!

di il
56 risposte

Non riesco a capire!

Salve a tutti
ho letto un interessantissimo articolo su come gestire gli errori in assembly
sotto il link se dovesse interessare anche ad altri.
( http://www.rohitab.com/structured-exception-handling-in-assembly-language )
adesso ho provato a mettere in pratica quello che avevo capito creando una semplice funzione che verificasse se una variabile e stata allocata o meno.
il problema è il seguente:
se la variabile alla prima chiamata non è allocata tutto funziona normalmente.
ma quando provo a mettere il codice all'interno di un loop non funziona più!
nel senso che se mi alloco una variabile di 5 elementi
ed eseguo un ciclo di 6 elementi mi restituisce che la variabile e sempre allocata anche quando non lo dovrebbe essere!
cosa ho sbagliato?
Pusha
Assume Fs:nothing
mov edi,Arg1 ;puntatore variabile da verificare
mov ebx,Arg2 ;puntatore variabile di ciclo
add edi,dword ptr [ebx]
MTry_Begin A0001 ;-------------------
mov byte ptr [edi],-6 ;* Test Scrittura. *
MTry_Except A0001 ;-------------------
mov eax,1
jmp short E0000
MTry_End A0001
jmp short A0004
E0000: mov errore,112
mov edi,Arg2
cmp byte ptr [edi],0
je A0004
inc errore
jmp short A0004
A0004: popa
xor eax,eax ; chiusura routine
mov al,errore
ret 12
le macro utilizzate sono le seguenti
MTry_Begin Macro handler
pushad
mov esi,offset handler
push esi
push Dword ptr fs:[0]
mov Dword ptr fs:[0],esp
EndM

MTry_Except Macro handler
jmp NoException
handler: mov esp,[esp + 8]
pop Dword ptr fs:[0]
add esp,4
popad
EndM

MTry_End Macro handler
jmp Exceptionhandled
NoException: pop Dword ptr fs:[0]
add esp,32 + 4
Exceptionhandled:
EndM

56 Risposte

  • Re: Non riesco a capire!

    Dove sta il ciclo di cui parli?

    Con quale tool compili? Con quale comando?
  • Re: Non riesco a capire!

    Ciao
    con il masm contenuto in Visual Studio enterprise 2019
  • Re: Non riesco a capire!

    Ovvero, quale è il sorgente completo che hai compilato?

    E il ciclo?
  • Re: Non riesco a capire!

    Il cilo viene fatto in c++
    for (int indy=0;indy <6;indy++)
    { errore=Verifica_variabile(stringa,indy,routine) }
    la routine è definita cosi
    extern "C" int __stdcall Verifica_Variabile(char*stringa,int &incremento,int &dimeroutine);
    nell'assembly lo si vede qui
    mov ebx,Arg2 ;puntatore variabile di ciclo
    add edi,dword ptr [ebx] ;somma la variabile di ciclo al puntatore della stringa allocata
  • Re: Non riesco a capire!

    Naturalmente il ciclo prevede anche la stampa del codice di ritorno variabile errore.
    che non ho messo xche al momento non è importante
  • Re: Non riesco a capire!

    Puoi postare tutto il codice C e l'ASM in maniera da compilarlo senza errori e senza doversi inventare nulla?

    E soprattutto, dire esattamente cosa ti succede e cosa invece ti aspetti?
  • Re: Non riesco a capire!

    Questo e il modulo c++
    #include "pch.h"
    #include <iostream>
    using namespace std;
    extern "C" int __stdcall Bianca2(char *&vettore, int dime, int opzione);
    extern "C" int __stdcall Verifica_Variabile(char *&indirizzo, int &nchiamata, int &routine);
    int main()
    {
    cout << "Hello World!\n"<<"Now Begin Test on Verifica_Variabile function\n";
    char *stringa;
    int errore,routine,nchiamata,indy;routine=0;nchiamata=0;
    errore=Bianca2(stringa,5,0);
    if (errore==0){ cout << "Abbiamo definito stringa indirizzo = " << *stringa<<"\n"; }
    else { cout<<"la routine Bianca2 e andata in errore restituendo "<<errore<<"\n"; return 0;}
    cout<<"Testiamo la routine Verifica_Variabile senza errore e con errore=113\n";
    for ( indy=0;indy<6;indy++)
    {
    errore=Verifica_Variabile(stringa,indy,routine);
    if(errore==113){cout<<"prova ok\n";}
    else
    {
    cout <<indy<<") la routine e' terminata con codice "<<errore<< " ed occupa "<<routine<<" byte in memoria\n";
    }
    }
    cout<<"testiamo Verifica_Variabile per errore 112\n";
    errore=Bianca2(stringa,5,1);
    if (errore!=0) { cout<<"la routine Bianca2 e andata in errore restituendo "<<errore<<"\n"; return 0;}
    errore=Verifica_Variabile(stringa,nchiamata,routine);
    if (errore!=112){cout<<"prova non riuscita\n"; return 0;}
    cout<<"Prova Riuscita!\n";
    return 0;
    }
  • Re: Non riesco a capire!

    Questo il modulo asm
    .486
    .model flat, stdcall
    option casemap:none
    .data
    errore db ?
    .code
    include macro\trouble_exception.mac
    Verifica_Variabile proc Arg1:Dword,Arg2:Dword,Arg3:Dword
    pusha
    Assume Fs:nothing
    mov edi,offset A0005
    inc edi ;-------------------------------
    mov ebx,Arg3 ;* Calcolo Dimensione Routine. *
    sub edi,offset A0000 ;-------------------------------
    mov dword ptr [ebx],edi
    A0000: mov errore,0
    mov edi,Arg1
    mov ebx,Arg2
    add edi,dword ptr [ebx]
    MTry_Begin A0001 ;-------------------
    mov byte ptr [edi],-6 ;* Test Scrittura. *
    MTry_Except A0001 ;-------------------
    mov eax,1
    jmp short E0000
    MTry_End A0001
    jmp short A0004
    E0000: mov errore,112
    mov edi,Arg2
    cmp byte ptr [edi],0
    je A0004
    inc errore
    A0004: popa
    xor eax,eax
    mov al,errore
    ret 12
    A0005:
    Verifica_Variabile Endp
    End
  • Re: Non riesco a capire!

    Questo e il modulo bianca2
    #include "stdafx.h"
    #include <iostream>
    #include <new>
    #include <cstdint>
    using std::bad_alloc;
    extern "C" int _stdcall Bianca2(char *&vettore,int dime,int opzione)
    {
    int errore = 0; int indy = 0;
    if ( dime == 0 ) { return 42; }
    dime++;
    switch (opzione)
    {
    case 0:
    {
    bool su_stack = vettore != nullptr;
    if (!su_stack)
    {
    vettore = new (std::nothrow) char [dime];
    }
    if (!vettore) { vettore=nullptr;errore=106; }
    break;
    }
    case 1:
    {
    if (vettore == nullptr) {errore=95;break;}
    delete [] vettore;
    vettore=nullptr; errore=1;
    break;
    }
    default: { errore=57; break; }
    }
    switch (errore)
    {
    case 1:{ errore = 0; break; }
    case 0:
    {
    for (indy=0;indy < dime-2;indy++)
    { vettore[indy] = ' '; }
    vettore[indy-1] = 0;break;
    }
    default: { break; }
    }
    dime--; return errore;
    }
  • Re: Non riesco a capire!

    Output ottenuto
    Testiamo la routine Verifica_Variabile senza errore e con errore=113
    0) la routine e' terminata con codice 0 ed occupa xxx byte in memoria
    1) la routine e' terminata con codice 0 ed occupa xxx byte in memoria
    2) la routine e' terminata con codice 0 ed occupa xxx byte in memoria
    3) la routine e' terminata con codice 0 ed occupa xxx byte in memoria
    4) la routine e' terminata con codice 0 ed occupa xxx byte in memoria
    5) la routine e' terminata con codice 0 ed occupa xxx byte in memoria
    b]testiamo Verifica_Variabile per errore 112
    Prova Riuscita!
    [/b]

    L'output che mi aspetto e il seguente:
    Testiamo la routine Verifica_Variabile senza errore e con errore=113
    0) la routine e' terminata con codice 0 ed occupa xxx byte in memoria
    1) la routine e' terminata con codice 0 ed occupa xxx byte in memoria
    2) la routine e' terminata con codice 0 ed occupa xxx byte in memoria
    3) la routine e' terminata con codice 0 ed occupa xxx byte in memoria
    4) la routine e' terminata con codice 0 ed occupa xxx byte in memoria
    prova ok
    testiamo Verifica_Variabile per errore 112
    Prova Riuscita!
    questa parte funzione!
  • Re: Non riesco a capire!

    Le macro sono quelle che ho postato all'inizio
    Spero che ora sia più chiaro il problema
  • Re: Non riesco a capire!

    Guarda ... il tuo codice è un caos ... non si capisce nulla di quello che fai né di quello che vorresti fare. Quindi non ti posso dire molto.
    Quello che posso fare è dirti cosa si può scrivere "semplicemente" e da dove puoi partire.
    Tieni presente che mi pare sia la solita questione di cui abbiamo tanto discusso tempo fa.
    Se la memoria a cui punta il puntatore non è allocata al processo (ad esempio il puntatore punta a NULL) allora puoi intercettare l'eccezione (anche semplicemente da C++ senza ASM) e operare di conseguenza. Ma se il puntatore punta casualmente a memoria del processo (ad altra variabile ad esempio), questo codice (e nessun altro codice) non ti potrà aiutare.

    Nell'esempio che segue l'errore custom 100 indica un problema di accesso alla memoria.

    Questo per un codice C che testa più byte a partire da un puntatore
    
    #include <iostream>
    using namespace std;
    
    extern "C" int __stdcall Verifica_Variabile(char *indirizzo);
    
    int main()
    {
    	int errore;
    	char *stringa = NULL;
    	
    	for (int quantevolte = 0; quantevolte < 5; quantevolte++)
    	{
    		errore = 0;
    		cout << "Indirizzo " << (void *)(stringa + quantevolte) << " ";
    		errore = Verifica_Variabile(stringa+quantevolte);
    		cout << "errore " << errore << endl;
    	}
    	
    	return 0;
    }
    
    con la funzione ASM
    
    .486
    .model flat, stdcall
    option casemap:none
    .data
    errore db ?
    .code
    
    ;;
    MTry_Begin Macro handler
    pushad
    mov esi,offset handler
    push esi
    push Dword ptr fs:[0]
    mov Dword ptr fs:[0],esp
    EndM
    
    MTry_Except Macro handler
    jmp NoException
    handler: mov esp,[esp + 8]
    pop Dword ptr fs:[0]
    add esp,4
    popad
    EndM
    
    MTry_End Macro handler
    jmp Exceptionhandled
    NoException: pop Dword ptr fs:[0]
    add esp,32 + 4
    Exceptionhandled:
    EndM
    ;;
    
    
    Verifica_Variabile proc Arg1:DWord
    	Assume Fs:nothing
    
    	pusha 
    	mov edi,Arg1
    
    	MTry_Begin SEHHDL
    	mov byte ptr [edi], 0
    
    	MTry_Except SEHHDL
    	mov errore,100
    
    	MTry_End SEHHDL
    	popa
    	xor eax,eax
    	mov al,errore
    	ret 4
    
    Verifica_Variabile EndP
    End
    
  • Re: Non riesco a capire!

    La stringa viene allocata
    e'il problema finche resto nel range allocato non sussiste.
    cosi come il problema non sussiste se la stringa non è allocata.
    il problema e' che mi da per buono anche quando la variabile punta ad un area non allocata e invece mi dovrebbe segnalare l'errore.
    lo devo scrivere in asm perchè in c++ potrei risolvere il problema con le try catch e quindi controllare se le variabili sono allocate.
    in asm non avendo la try catch al momento non posso fare ed ecco perchè di questa routine.
  • Re: Non riesco a capire!

    Come ti dicevo anche l'altra volta e ti ripeto adesso, sia in C sia in Asm, se la memoria che segue è comunque riservata al tuo processo, anche se non allocata, avrai sempre questo tipo di funzionamento perché gli indirizzi saranno comunque validi. E questo non puoi facilmente prevederlo per tanti motivi. Ma so già che non riuscirò a cpnvincerti perché tu non ti rendi conto del funzionamento a questo livello di CPU e OS.
Devi accedere o registrarti per scrivere nel forum
56 risposte