Essendo uno degli ultimi possessori di un processore della famiglia PowerPC non potevo resistere alla tentazione di scoprire le caratteristiche interne di questa meravigliosa macchina.
Il processore appartiene alla famiglia RISC,cioè ha un set di istruzioni limitato nelle funzionalità,(load and store), presenta un banco di 31 registri in virgola fissa a 32 bit e un banco di 32 registri in virgola mobile a 64 bit e alcuni registri di uso speciale.
In giro si trova parecchio materiale a riguardo,ho trovato un paio di references : semplificata
ed estesa
ma scarseggiavano un pò gli esempi e il codice.
Con il compilatore gcc però si può effettuare la compilazione senza assemblare il programma in codice eseguibile, adoperando
gcc -S -o programma nomesorgente.c
e grazie a questo, è possibile studiare semplici programmi scritti ad alto livello e tradotti in assembly.
Dopo aver capito meglio il funzionamento dello stack e dei registri di uso speciale, ho scritto qualcosina a mano anche io:
#Hello world stampato dalla funzione HELLO .data MSG: .string "Hello World!!\n" len = . -MSG #len è dato dalla differenza tra la locazione corrente e la locazione di MSG .text .align 2 .globl main HELLO: li 0,4 #in R0 va il riferimento della system call,la n°4 è write li 3,1 #in R3 va il primo parametro, 1 è l'identificatore dello stdout lis 4,MSG@ha #carico i 16 bit più significativi dell'indirizzo della stringa su R4 #con lis li shifto di mezza parola a sinistra addi 4,4,MSG@l #piazzo i 16 bit meno significativi di MSG su R4 li 5,len #piazzo il terzo parametro cioè la lunghezza della stringa in R5 sc #chiamo la system call n° 4 blr #ritorno al main main: stwu 1,-16(1) #R1 è lo stack pointer,avanzo lo stack pointer di 16 bytes,nei primi 4 bytes alloco l'R1 vecchio mflr 0 #carico in R0 il linkregister, in esso vi è l'indirizzo di ritorno del main,mi serve per uscire stw 0 ,12(1) #inserisco una copia di lr sullo stack bl HELLO #passo alla funzione HELLO e carico sul lr #l'indirizzo di ritorno,cioè la locazione successiva lwz 0 ,12(1) #ritornando dalla funzione riprendo l'indirizzo #di ritorno del main dallo stack e lo pongo in R0 mtlr 0 #rimetto l'indirizzo in lr addi 1,1,16 #chiudo lo stack del main blr #salto all'indirizzo di ritorno ed esco
#Spawn di un processo .data file: .string "/usr/bin/gcalctool" error: .string "Errore ci fù!" .align 2 .text .globl main .align 2 main: stwu 1,-20(1) #creo lo stackframe del main mflr 30 stw 30,4(1) #pongo lr nello stack stw 3,8(1) stw 4,12(1) stw 5,16(1) #come anche i 3 parametri bl spawn lwz 30,4(1) #recupero lr lwz 3,8(1) lwz 4,12(1) lwz 5,16(1) # e i parametri mtlr 30 blr spawn: stwu 1,-20(1) #creo lo stack frame della funzione spawn mflr 30 stw 30,4(1) #e vi pongo i parametri del main passati alla spawn stw 3,8(1) stw 4,12(1) stw 5,16(1) li 0,2 #kernel fork pronta sc cmpwi 7,3,0 #confronto il valore di ritorno della fork con 0 ponendo in cr[7] l'esito beq 7,son #se è uguale a 0 sono il figlio addi 1,1,20 #chiudo lo stackframe blr #altrimenti torno al main son: li 0 ,11 #sono il figlio e quindi effettuo l'exec lis 3,file@ha addi 3,3,file@l lwz 30,4(1) #recupero lr lwz 4,12(1) lwz 5,16(1) # e i parametri sc lis 3,error@ha #in caso di mancata esecuzione della exec addi 3,3,error@l b puts #stampo un errore blr #e torno al main




















15 Luglio 2008 alle 5:54 pm |
Molto utile! Chiaro e completo… erano mesi che cercavo degli esempi come questi!
Grazie!