Gestione dello stak in 8086

di il
7 risposte

Gestione dello stak in 8086

Avrei bisogno di una mano. Mi è stata data una esercitazione in cui data una stringa in input devo stamparla al contrario, verificare se palindroma e stampare una sotto stringa dato il carattere iniziale e finale. per fare ciò avrei bisogno di una spiegazione e possibilmente un piccolo esempuio pratico su come si acquisiscono i dati dallo stack senza usare l'istruzione pop ma con l'ausilio di BP e SP in modo da tenere lo stack intatto e poter prelevare un qualsiasi valore indipendentemente dalla posizione nello stack.
Grazie in anticipo

7 Risposte

  • Re: Gestione dello stak in 8086

    Stai PASTICCIANDO con CONCETTI FONDAMENTALI!

    Una cosa e' LO STACK delle chiamate alle funzioni, gestito da BP e SP, E QUESTO NON LO PUOI TOCCARE,

    Un'altra cosa e' lo stack come struttura dati, che DEVI IMPLEMENTARE TU.

    Tutti e due funzionano come uno stack, MA quello delle chiamate e' gestito DIRETTAMENTE dalla CPU.
  • Re: Gestione dello stak in 8086

    migliorabile ha scritto:


    Stai PASTICCIANDO con CONCETTI FONDAMENTALI!

    Una cosa e' LO STACK delle chiamate alle funzioni, gestito da BP e SP, E QUESTO NON LO PUOI TOCCARE,

    Un'altra cosa e' lo stack come struttura dati, che DEVI IMPLEMENTARE TU.

    Tutti e due funzionano come uno stack, MA quello delle chiamate e' gestito DIRETTAMENTE dalla CPU.
    Allora cosa dovrei fare nel caso dovessi prelevare dei valori dallo stack senza usare le comuni push e pop in modo da poter prelevare in qualsiasi punto della pila non rispettandone la logica?
  • Re: Gestione dello stak in 8086

    Probabilmente ti riferisci all'uso dello

    stack frame

    Fai una ricerca si quei termini per avere indicazioni
  • Re: Gestione dello stak in 8086

    migliorabile ha scritto:


    Stai PASTICCIANDO con CONCETTI FONDAMENTALI!

    Una cosa e' LO STACK delle chiamate alle funzioni, gestito da BP e SP, E QUESTO NON LO PUOI TOCCARE,

    Un'altra cosa e' lo stack come struttura dati, che DEVI IMPLEMENTARE TU.

    Tutti e due funzionano come uno stack, MA quello delle chiamate e' gestito DIRETTAMENTE dalla CPU.
    @nonc'èsperanzachemigliori: che fregnaccia colossale! Questo dimostra che di Assembly 8086 non sai niente!
    TUTTE le funzioni usano lo Stack per l'allocazione delle variabili temporanee e per il passaggio dei parametri!
    Nell'immagine un esempio.
    stack1.PNG
    stack1.PNG

    Il sorgente della funzione:
    Function TFBase64.Prova(Const Numero:integer):integer;
    Var
      a, b : double;
    begin
      a := Numero;
      b := a * 3.14;
      Result := Trunc(b + 0.5);
    end; //Prova
    
    Osserva come
    - all'inizio della funzione EBP viene salvato
    - EBP prende il valore di ESP cioè dell'ultima locazione usata (c'è il vecchio valore di EBP)
    - ESP viene DIMINUITO di un tot di byte: lo Stack cresce verso il basso!
    A quel punto EBP viene usato come puntatore alle variabili locali e al risultato della funzione.
    Alla fine della funzione ESP viene ripristinato ricopiandolo da EBP e liberando quindi lo spazio allocato, infine viene ripristinato EBP: gli altri registri spesso non sono conservati oppure sono usati per il passaggio di parametri ma EBP è fondamentale per l'uso che se ne fa.

    Da notare anche che:
    - il codice è scritto in Delphi
    - le ottimizzazioni sono spente
    - il controllo "Range checking" è acceso

    Gli altri linguaggi compilati fanno un uso quasi identico dello Stack, le differenza, di solito, sono stilistiche.
  • Re: Gestione dello stak in 8086

    nicolap ha scritto:


    migliorabile ha scritto:


    Stai PASTICCIANDO con CONCETTI FONDAMENTALI!

    Una cosa e' LO STACK delle chiamate alle funzioni, gestito da BP e SP, E QUESTO NON LO PUOI TOCCARE,

    Un'altra cosa e' lo stack come struttura dati, che DEVI IMPLEMENTARE TU.

    Tutti e due funzionano come uno stack, MA quello delle chiamate e' gestito DIRETTAMENTE dalla CPU.
    @nonc'èsperanzachemigliori: che fregnaccia colossale! Questo dimostra che di Assembly 8086 non sai niente!
    TUTTE le funzioni usano lo Stack per l'allocazione delle variabili temporanee e per il passaggio dei parametri!
    Nell'immagine un esempio.
    stack1.PNG

    Il sorgente della funzione:
    Function TFBase64.Prova(Const Numero:integer):integer;
    Var
      a, b : double;
    begin
      a := Numero;
      b := a * 3.14;
      Result := Trunc(b + 0.5);
    end; //Prova
    
    Osserva come
    - all'inizio della funzione EBP viene salvato
    - EBP prende il valore di ESP cioè dell'ultima locazione usata (c'è il vecchio valore di EBP)
    - ESP viene DIMINUITO di un tot di byte: lo Stack cresce verso il basso!
    A quel punto EBP viene usato come puntatore alle variabili locali e al risultato della funzione.
    Alla fine della funzione ESP viene ripristinato ricopiandolo da EBP e liberando quindi lo spazio allocato, infine viene ripristinato EBP: gli altri registri spesso non sono conservati oppure sono usati per il passaggio di parametri ma EBP è fondamentale per l'uso che se ne fa.

    Da notare anche che:
    - il codice è scritto in Delphi
    - le ottimizzazioni sono spente
    - il controllo "Range checking" è acceso

    Gli altri linguaggi compilati fanno un uso quasi identico dello Stack, le differenza, di solito, sono stilistiche.
    Allora, ho notato che hai capito la mia richiesta, però ti chiederei una cortesia se possibile. Io sono in 3° superiore e le cose che so di assembly sono legate all'assembly stesso. Non abbiamo visto l'assembly in funzione di altri linguaggi, abbiamo solo programmato in 8086. Se vuoi ti faccio anche vedere un mio programma per renderti conto del livello a cui sono. Detto ciò, grosso modo credo di aver capito il concetto, ma se è possibile fare un'altro esempio non scritto il delphi ma con un qualcosa di simile a quello allegato qui di sotto capirei meglio. Comunque ne so più di prima quindi grazie lo stesso.
    
       .MODEL SMALL     		; definisce il modello di memoria da utilizzare
       .STACK 100h      		; dimensione massima del codice sorgente
    
       .DATA            		; definizione delle stringhe
       inserimento       DB   'Inserisci un numero ','$'
       Decimale          DB   'Il risultato in decimale equivale a ','$'
       Binario           DB   'Il risultato in binario equivale a ','$'
       Esadecimale       DB   'Il risultato in esadecimale equivale a ','$'
       Ottale            DB   'Il risultato in ottale equivale a ','$'
       accapo            DB    13,10,'$'
       ricalcola         DB   'Per rieseguire il programma da capo digita 1:  ','$'
    
       .CODE            		; inizio codice sorgente
    
       mov ax,@data
       mov ds,ax			; imposta DS per puntare al segmento di dati
    
       sub ax,ax			; azzerare il registro ax
    
    ;	||***********||
    ;	||INSERIMENTO||
    ;	||***********||
    JMP INIZIO2
    
    INIZIO:
    
    
       mov dx,OFFSET accapo		; fa andare accapo il testo
       mov ah,09h                  
       int  21h
    
    INIZIO2:
    
       mov dx,OFFSET inserimento	; stampa d'inserimento del primo numero
       mov ah,09h                  
       int  21h
      
       mov ah,01h			; acquisisce delle decine del primo numero
       int 21h
    
       sub ah,ah			; controlla se il valore acquisito in input è un numero
       cmp ax,30h
       JL INIZIO
       cmp ax,39h
       JG INIZIO
    
       sub al,30h			; porta il valore preso da tastiera al valore effettivo
    
       mov bh,0Ah			; moltpiplica il valore contenuto in ax per quello di bh
       mul bh
    
       mov bl,al			; il risultato della moltiplicazione viene salvato in bl
    
       mov ah,01h			; acquisisce delle unità primo numero
       int 21h
    
       sub ah,ah			; controlla se il valore acquisito in input è un numero
       cmp ax,30h
       JL INIZIO
       cmp ax,39h
       JG INIZIO
    
       sub al,30h			; porta il valore preso da tastiera al valore effettivo	
    
       add bl,al			; somma il valore appena acquisito al risultato della moltiplicazione precedente per formare il valore complessivo
    
       mov dx,OFFSET accapo		; Fa andare accapo il testo
       mov ah,09h                  
       int  21h
    
    
       mov dx,OFFSET inserimento	; stampa d'inserimento del secondo numero
       mov ah,09h                  
       int  21h
    
       mov ah,01h			; acquisisce delle decine del secondo numero
       int 21h
    
       sub ah,ah			; controlla se il valore acquisito in input è un numero
       cmp ax,30h
       JL INIZIO
       cmp ax,39h
       JG INIZIO
    
       sub al,30h			; porta il valore preso da tastiera al valore effettivo	
    
       mul bh			; moltpiplica il valore contenuto in ax per quello di bh
    
       add bl,al
    
       mov ah,01h			; acquisisce delle decine del secondo numero
       int 21h
    
       sub ah,ah			; stampa d'inserimento del secondo numero
       cmp ax,30h
       JL INIZIO
       cmp ax,39h
       JG INIZIO
    
       sub al,30h			; porta il valore preso da tastiera al valore effettivo	
    
       add bl,al
    
       mov dx,OFFSET accapo		; fa andare accapo il testo
       mov ah,09h                  
       int  21h
      
       sub bh,bh
       push bx			; salvataggio del risultato della somma
       mov ax,bx
    
    ;	||*******************||
    ;	||CALCOLO IN DECIMALE||
    ;	||*******************||
    
       cmp ax,0Ah			; controlla se maggiore
       JGE ALLORA1
       add al,30h			; codifica ASCII della somma
       JMP RISULTATO
    
    ALLORA1:
       mov ch, 0h			;inizializzazione a 0
    FOR1:
       sub al, 0Ah			; spartizione delle cifre nei vari registi
       inc ch			; ch=decine al=untià
       cmp ax,0Ah
       JGE FOR1
       
       cmp ch,0Ah			; controlla se le decine sono maggiori di 0A
       JL RISULTATO2
       sub ch,0Ah			; ulteriore spartizione
       mov cl,01h			; cl centinaia 
       JMP RISULTATO3
    
    ;	||******************||
    ;	||STAMPA IN DECIMALE||
    ;	||******************||
    
    RISULTATO:
       mov bl,al
       mov dx,OFFSET Decimale	; stampa della stringa risultato 
       mov ah,09h                  
       int  21h
    
       mov dl,bl 			; stampa della cifra
       mov ah,02h                  
       int  21h
    
       JMP OTTALE1
    
    RISULTATO2:
       mov bl,al
       mov dx,OFFSET Decimale	; stampa della stringa risultato 
       mov ah,09h                  
       int  21h
    
       mov dl,ch			; stampa delle decine
       add dl,30h 
       mov ah,02h                  
       int  21h
    
       mov dl,bl			; stampa delle unità
       add dl,30h
       mov ah,02h                  
       int  21h
    
       JMP OTTALE1
    
    RISULTATO3:
    
       mov bl,al
       mov dx,OFFSET Decimale	; stampa della stringa risultato 
       mov ah,09h                  
       int  21h
    
       mov dl,cl			; stampa delle centinaia
       add dl,30h 			
       mov ah,02h                  
       int  21h
    
       mov dl,ch			; stampa delle decine
       add dl,30h 
       mov ah,02h                  
       int  21h
    
       mov dl,bl			; stampa delle unità
       add dl,30h
       mov ah,02h                  
       int  21h
    
    
    ;	||*****************||
    ;	||CALCOLO IN OTTALE||
    ;	||*****************||
    
    OTTALE1:
    
       mov dx,OFFSET accapo		; fa andare accapo il testo
       mov ah,09h                  
       int  21h
    
       pop ax			; assegnazione ad bl della somma dei due numeri
       push ax			; salvataggio del risultato della somma
    
       cmp ax,08h			; controllo se il risultato è maggiore di 08
       JGE ALLORA2
       add al,30h			; conversone in codifica ASCII
       JMP RISOTTALE1
    
    ALLORA2:
       mov ch, 0h			; spartizione delle cifre su vari registi
    FOR2:				; ch=decine al=unità
       sub al, 08h
       inc ch
       cmp ax,08h
       JGE FOR2
       
       cmp ch,08h			; controllo sulle centinaia
       JL RISOTTALE2		; cl=centinaia
       sub cl,cl
    FOR21:
       sub ch, 08h
       inc cl
       cmp ch,08h
       JGE FOR21
    
       JMP RISOTTALE3
    ;	||****************||
    ;	||STAMPA IN OTTALE||
    ;	||****************||
    
    RISOTTALE1:
       mov dx,OFFSET accapo		; fa andare accapo il testo
       mov ah,09h                  
       int  21h
    
       mov bl,al
       mov dx,OFFSET Ottale		; stampa della stringa risultato 
       mov ah,09h                  
       int  21h
    
       mov dl,bl 			; stampa delle unità
       mov ah,02h                  
       int  21h
    
       JMP ESADECIMALE1
    
    RISOTTALE2:
       mov dx,OFFSET accapo		; fa andare accapo il testo
       mov ah,09h                  
       int  21h
    
       mov bl,al
       mov dx,OFFSET Ottale		; stampa della stringa risultato 
       mov ah,09h                  
       int  21h
    
       mov dl,ch			; stampa delle decine
       add dl,30h 
       mov ah,02h                  
       int  21h
    
       mov dl,bl			; stampa delle unità
       add dl,30h
       mov ah,02h                  
       int  21h
    
       JMP ESADECIMALE1
    
    RISOTTALE3:
    
       mov bl,al
       mov dx,OFFSET Ottale		; stampa della stringa risultato 
       mov ah,09h                  
       int  21h
    
       mov dl,cl			; stampa delle centinaia
       add dl,30h 
       mov ah,02h                  
       int  21h
    
       mov dl,ch			; stampa delle decine
       add dl,30h 
       mov ah,02h                  
       int  21h
    
       mov dl,bl			; stampa delle unità
       add dl,30h
       mov ah,02h                  
       int  21h
    
    ;	||**********************||
    ;	||CALCOLO IN ESADECIMALE||
    ;	||**********************||
    
    ESADECIMALE1:
       pop ax			; assegnazione ad bl della somma dei due numeri
       push ax			; salvataggio del risultato della somma
    
       cmp ax,10h			; controllo se la somma è maggiore di 10
       JGE ALLORA3
       add al,30h			; conversione codifica ASCII
       JMP RISESADECIMALE1
    
    ALLORA3:			; spartizione delle cifre su vari registi
       mov ch, 0h			; ch=decine al=unità
    FOR3:
       sub al, 10h
       inc ch
       cmp ax,10h
       JGE FOR3
       JMP RISESADECIMALE2
    
    ;	||*********************||
    ;	||STAMPA IN ESADECIMALE||
    ;	||*********************||
    
    RISESADECIMALE1:
       mov dx,OFFSET accapo		; fa andare accapo il testo
       mov ah,09h                  
       int  21h
    
       mov bl,al			; controllo se il valore sia maggiore di 09 per la stampa dei caratteri
       cmp bl, 3Ah
       JL RIS1
       add bl,07h
    RIS1:
       mov dx,OFFSET Esadecimale	; stampa della stringa risultato 
       mov ah,09h                  
       int  21h
    
       mov dl,bl 			; stampa delle unità
       mov ah,02h                  
       int  21h
    
       JMP BINARIO1
    
    RISESADECIMALE2:
       mov dx,OFFSET accapo		;fa andare accapo il testo
       mov ah,09h                  
       int  21h
    
       mov bl,al
       mov dx,OFFSET Esadecimale	; stampa della stringa risultato 
       mov ah,09h                  
       int  21h
    
       mov dl,ch			; stampa delle decine
       cmp dl, 0Ah
       JL RIS2
       add dl,07h
    RIS2:
       add dl,30h 
       mov ah,02h                  
       int  21h
    
       mov dl,bl			; stampa delle unità
       cmp dl, 0Ah
       JL RIS3
       add dl,07h
    RIS3:
       add dl,30h
       mov ah,02h                  
       int  21h
       JMP BINARIO1
    
    
    ;	||******************||
    ;	||CALCOLO IN BINARIO||
    ;	||******************||
    
    BINARIO1:
       pop ax			; assegnazione ad bl della somma dei due numeri
    
       sub cx,cx
       
       mov bl,01h			; salvataggio del valore 1 in bl
       sub dx,dx			; azzeramento del registro dx per assegnarli il valore 0
    
    CICLO1:				; tramite le divisioni avviene la conversione  in binario
       inc bl			; se il resto della divisione è diverso da 0 esegue la push di 1, se è uguale a 0 fa la push del di 0
       div bl			
       dec bl
       cmp ah,00h
       JNE ELSE1
       push dx
       JMP FIN1
    ELSE1:
       push bx
    FIN1:
       mov cl,al
       inc ch
       mov ax,cx
       sub ah,ah
    
       cmp ax,00h
       JG CICLO1
    
    ;	||*****************||
    ;	||STAMPA IN BINARIO||
    ;	||*****************||
    
    RISBINARIO1:
       mov cl,ch			; assegnazione di cl e azzeramento di ch
       sub ch,ch			; cx usato in seguito per il ciclo for
       mov dx,OFFSET accapo		; fa andare accapo il testo
       mov ah,09h                  
       int  21h
    
       mov dx,OFFSET Binario	; stampa della stringa risultato
       mov ah,09h                  
       int  21h
    
    FOR4:
       pop dx			; stapa del risultato tramite ciclo for
       add dl,30h
       mov ah,02h                  
       int  21h
       LOOP FOR4
    
    
       mov dx,OFFSET accapo		; fa andare accapo il testo
       mov ah,09h                  
       int  21h
    
    
       mov dx,OFFSET accapo		; fa andare accapo il testo
       mov ah,09h                  
       int  21h
    
       mov dx,OFFSET ricalcola	; stampa la stringa ricalcola
       mov ah,09h                  
       int  21h
    
       mov ah,01h			; acquisisce la risposta del ricalcola
       int 21h
       
       sub ah,ah			; condizione di salto 
       cmp ax,31h
       JNE FINE
       JMP INIZIO
       
    
    FINE:
       mov  ah,4ch            ;funzione dos per terminare il programma
       int  21h               ;termina il programma
       END                    ;END va sempre messo alla fine del programma
    
  • Re: Gestione dello stak in 8086

    Ripeto studia il concetto di stackframe
  • Re: Gestione dello stak in 8086

    Voglio_Morire ha scritto:


    Allora, ho notato che hai capito la mia richiesta, però ti chiederei una cortesia se possibile. Io sono in 3° superiore e le cose che so di assembly sono legate all'assembly stesso. Non abbiamo visto l'assembly in funzione di altri linguaggi, abbiamo solo programmato in 8086. Se vuoi ti faccio anche vedere un mio programma per renderti conto del livello a cui sono. Detto ciò, grosso modo credo di aver capito il concetto, ma se è possibile fare un'altro esempio non scritto il delphi ma con un qualcosa di simile a quello allegato qui di sotto capirei meglio. Comunque ne so più di prima quindi grazie lo stesso.
    Non importa il fatto che il codice del mio esempio derivi dalla compilazione di codice Delphi: illustra in maniera semplice l'uso dello Stack per certi scopi.

    Non ho tempo di leggere tutto il codice ma già all'inizio ci sono delle cose strane:
       .STACK 100h      		; dimensione massima del codice sorgente
    Il commento è del tutto sbagliato.
    Poco più sotto azzeri ax e lo scrivi nel commento. Il commento è del tutto inutile perché chiunque conosca un minimo di Assembly capisce da solo COSA faccia l'istruzione, molto più importante è sapere PERCHÉ lo fai. E in effetti non se ne capisce il motivo!
    Infine non puoi usare lo stack come stai facendo, i push e i pop devono essere sempre "vicini" in modo da riuscire a tenerli appaiati, altrimenti sputtani(*) lo stack in un nanosecondo.
    Riguarda il frammento che ti ho postato e analizzalo, riscrivilo mettendo delle costanti simboliche al posto dei valori hex.


    PS: "accapo" non si scrive certo così! Sono due parole separate.
    (*) è un termine tecnico
Devi accedere o registrarti per scrivere nel forum
7 risposte