È possibile chiamare in modo sicuro funzioni da una funzione nuda, a condizione che le funzioni chiamate abbiano un prologo completo ed un epilogo.
Si noti che è un po 'assurdo affermare che è possibile "tranquillamente" utilizzare il linguaggio assembly in una funzione nuda. Sei completamente responsabile per qualsiasi cosa tu usi il linguaggio assembly, così come lo sei per ogni chiamata che fai a funzioni 'sicure'.
Per garantire che la funzione chiamata generica non sia statica o in linea, dovrebbe essere in un'unità di compilazione separata.
Le funzioni "nude" non includono alcun prologo o epilogo: sono nudi. In particolare, non includono le operazioni sullo stack per le variabili locali, per salvare o ripristinare i registri o per tornare a una funzione di chiamata.
Ciò non significa che nessuno stack esiste: lo stack viene inizializzato nell'inizializzazione del programma, non in qualsiasi inizializzazione di funzione. Poiché esiste uno stack, i cosiddetti prologhi delle funzioni e gli epiloghi funzionano correttamente. Una chiamata di funzione può tranquillamente inviare il suo indirizzo di ritorno, tutti i registri utilizzati e lo spazio per eventuali variabili locali. Al ritorno (usando l'indirizzo di ritorno), i registri vengono ripristinati e lo spazio di stack viene rilasciato.
Le funzioni statiche o inline possono non avere un prologo completo ed un epilogo. Possono e possono dipendere dalla funzione chiamante per gestire lo stack e ripristinare i registri danneggiati.
Questo porta al punto successivo: è necessario il prologo e l'epilogo solo per incapsulare le operazioni della funzione chiamata.Se la funzione chiamata è anche sicura (nessuna variabile locale esplicita o implicita, nessuna modifica ai registri di stato), può essere statica e/o in linea sicura. Come con asm, sarebbe tua responsabilità assicurarti che sia vero.
Ho fatto la mia domanda, perché nella fonte di FreeRTOS per AVR ho visto il seguente void vPortYield (void) __attribute__ ((naked)); void vPortYield (void) { \t portSAVE_CONTEXT(); \t vTaskSwitchContext(); \t portRESTORE_CONTEXT(); \t asm volatile ("ret"); } portSAVE_CONTEXT() e portRESTORE_CONTEXT() sono macrose con asm ma vTaskSwitchContext è una funzione. –
Questa risposta non è corretta. Puoi fare qualsiasi cosa in una funzione nuda che faresti da qualsiasi altra parte purché tu realizzi l'ABI: questo significa che devi conoscere, capire ed essere in grado di prevedere in modo affidabile l'ABI che stai usando. Inoltre, la documentazione non è corretta, perché è possibile accedere in modo sicuro alle variabili globali dall'istruzione asm senza effetti collaterali indesiderati, ma se lo si deve inserire "memoria" nei clobbers. –