Estratto del documento

Da C ad assembly

Conversione di un programma da C ad assembly

Data: April 18, 2021, 10:50 PM

Tags: Calcolatori

Programma in C da convertire

#include <iostream>

int FIB (int n) {
    if (n == 0)
        return 0;
    else if (n < 2)
        return 1;
    else
        return (FIB(n-1) + FIB(n-2)); // chiamo più volte FIB e ogni volta ho bisogno di salvare l'indirizzo di ritorno
}

/*int main () {
    int n=5;
    bool condotion = true;
    while (condition) {
        FIB (n);
        n-=1;
        condition = (n>=0) ? false : true;
    }
    return 0;
}*/

Gestione del registro di ritorno

$ra contiene sempre l'indirizzo di ritorno (unico per questo scopo). Con la chiamata più volte di FIB, sovrascrivo ogni volta il valore di $ra, perdendo quello precedente. Ciò riguarda qualunque altro registro che riutilizzo, andando a sovrascrivere il nuovo al vecchio. Come faccio a non perdere il contenuto? → Uso la memoria.

Devo preoccuparmi di non perdere il valore di un registro prima di sovrascriverlo. Per fare ciò, devo salvarlo/copiarlo da qualche parte (ovvero in memoria, in particolare in una cella riservata a salvare quel dato).

Convenzione per funzioni ricorsive

Si usa non la memoria in generale ma lo stack, zona di memoria "a pila".

FIB: 
    addi $sp, $sp, -12 # alloco lo stack
    sw $ra, 8($sp)     # salvo return address
    sw $a0, 4($sp)     # salvo n
    sw $s1, 0($sp)     # salvo risultato parziale
    # FIB definita nel suo funzionamento

All'inizio, decremento lo stack pointer di 12 in quanto sto utilizzando tre valori da 4 Byte l'uno, ovvero 12 Byte. Devo, dunque, spostare l'indirizzo iniziale dello stack di 12 posizioni (in basso perché lo stack è una pila verso il basso). Con gli sw, salvo nelle varie zone dello stack i valori dei registri che voglio preservare. Questo è da fare all'inizio della funzione ricorsiva, per preservare i valori ogni volta.

Condizioni e salti

IF: 
    bgtz $a0, ELSEIF  # branch -> salto a ELSEIF se n>0
    add $v0, $zero, $zero # metto dentro a $v0 il valore 0 se n==0 (ovvero, se n==0 ritorna 0)
    j END             # mi aspettavo jr $ra -> salto all'indirizzo corrispondente al valore contenuto in $ra
                      # questo, invece, è sempre un salto incondizionato ma a un'etichetta specifica (END). Infatti, devo ripristinare $ra
ELSEIF: 
    slti $t0, $a0, 2  # set $t0 <-- 1 se $a0<2
    beq $t0, $zero, ELSE # se $t0==0 salta a ELSE condizionatamente (ovvero se n>=2)
    addi $v0, $zero, 1 # se n==1 ritorna 1
    j END

L'uso dello stack consente di gestire correttamente l'indirizzo di ritorno ($ra) e altri registri che devono essere preservati tra le chiamate di funzioni ricorsive.

Anteprima
Vedrai una selezione di 1 pagina su 2
Conversione da C ad Assembly Pag. 1
1 su 2
D/illustrazione/soddisfatti o rimborsati
Acquista con carta o PayPal
Scarica i documenti tutte le volte che vuoi
Dettagli
SSD
Ingegneria industriale e dell'informazione ING-INF/05 Sistemi di elaborazione delle informazioni

I contenuti di questa pagina costituiscono rielaborazioni personali del Publisher vale_condo di informazioni apprese con la frequenza delle lezioni di architettura dei calcolatori e studio autonomo di eventuali libri di riferimento in preparazione dell'esame finale o della tesi. Non devono intendersi come materiale ufficiale dell'università Università degli studi di Genova o del prof Baglietto Pierpaolo.
Appunti correlati Invia appunti e guadagna

Domande e risposte

Hai bisogno di aiuto?
Chiedi alla community