Avanti Indietro Indice

5. CONVENZIONI DI CHIAMATA

5.1 Linux

Linking a GCC

È il modo preferito. Controllate la documentazione di GCC e gli esempi dai file .S del kernel di Linux che passano attraverso gas (non quelli che passano attraverso as86).

Gli argomenti a 32 bit vengono posti sullo stack (push) in ordine inverso rispetto alla sintassi (per cui vi si accede prelevandoli nell'ordine corretto) sopra l'indirizzo di ritorno a 32 bit. %ebp, %esi, %edi, %ebx sono salvati dalla funzione chiamata, gli altri dalla funzione chiamante; per contenere il risultato si usa %eax, oppure %edx:%eax per risultati a 64 bit.

Stack FP: non ne sono certo, ma penso che il risultato vada in st(0) e che l'intero stack sia salvato dalla funzione chiamante. Notate che GCC ha delle opzioni per modificare le convenzioni di chiamata riservando registri, per mettere argomenti nei registri, per non fare supposizioni sulla presenza dell'FPU, ecc. Controllate le pagine .info i386 .

Fate attenzione: in questo caso dovete dichiarare l'attributo decl per una funzione che seguirà le convenzioni di chiamata standard di GCC (non so cosa faccia con le convenzioni di chiamata modificate). Leggete le pagine info di GCC nella sezione: C Extensions::Extended Asm::

ELF ed a.out : problemi.

Alcuni compilatori C antepongono un underscore prima di ogni simbolo, mentre altri non lo fanno.

In particolare, GCC a.out per Linux effettua questa anteposizione, mentre GCC ELF per Linux no.

Se avete bisogno di gestire insieme entrambi i comportamenti, guardate come fanno i pacchetti esistenti. Ad esempio, procuratevi dei vecchi sorgenti di Linux, Elk, qthreads, o OCAML...

Potete inoltre far ignorare la rinominazione implicita C->asm inserendo istruzioni come


        void pippo asm("pluto") (void);

per essere sicuri che la funzione C «pippo» venga chiamata davvero «pluto» in assembly.

Notate che il programma di utilità objcopy, dal pacchetto binutils, dovrebbe permettervi di trasformare i vostri oggetti a.out in oggetti ELF e forse anche viceversa, in alcuni casi. Più in generale, effettuerà un gran numero di conversioni di formato dei file.

Linux: chiamate di sistema dirette

Ciò è espressamente NON consigliato, poiché le convenzioni cambiano di tanto in tanto o tra varianti del kernel (vedere L4Linux), inoltre si perde la portabilità, comporta un lavoro di scrittura massiccio, si ha ridondanza con gli sforzi di libc ED INOLTRE preclude estensioni e correzioni apportate a libc come, ad esempio, il pacchetto zlibc, che provvede ad una trasparente decompressione «al volo» di file compressi con gzip. Il metodo convenzionale e consigliato per chiamare i servizi di sistema di Linux è, e rimarrà, quello di passare attraverso la libc.

Gli oggetti condivisi dovrebbero mantenere la vostra roba entro dimensioni contenute. E se proprio volete binari più piccoli, utilizzate #! e scaricate sull'interprete il fardello che volete togliere dai vostri binari.

Ora, se per qualche ragione non volete fare un link alla libc, procuratevi la libc stessa e capite come funziona! Dopotutto, aspirate a sostituirla, no?

Potreste inoltre dare un'occhiata a come il mio eforth 1.0c lo fa.

Anche i sorgenti di Linux tornano utili, in particolare l'header file asm/unistd.h, che descrive come effettuare le chiamate di sistema...

Fondamentalmente, generate un int $0x80, con il numero associato a __NR_nomedellasyscall (da asm/unistd.h) in %eax, ed i parametri (fino a cinque) in %ebx, %ecx, %edx, %esi, %edi rispettivamente. Il risultato viene restituito in %eax, dove un numero negativo è un errore il cui opposto è ciò che libc metterebbe in errno. Lo stack utente non viene toccato, così non è necessario averne uno valido quando effettuate una chiamata di sistema.

I/O sotto Linux

Se volete effettuare dell'I/O sotto Linux, o si tratta di qualcosa di molto semplice che non richiede l'arbitraggio del sistema operativo, e allora dovreste consultare l'IO-Port-Programming mini-HOWTO, oppure ha bisogno di un driver di periferica nel kernel, nel qual caso dovreste provare ad approfondire le vostre conoscenze sull'hacking del kernel, sullo sviluppo di driver di periferica, sui moduli del kernel, ecc., per i quali ci sono altri eccellenti HOWTO e documenti del LDP.

In particolare, se ciò che vi interessa è la programmazione della grafica, allora partecipate al progetto GGI: http://synergy.caltech.edu/~ggi/ http://sunserver1.rz.uni-duesseldorf.de/~becka/doc/scrdrv.html

Comunque, in tutti questi casi, fareste meglio ad usare l'assembly inline di GCC con le macro da linux/asm/*.h piuttosto che scrivere file sorgenti completamente in assembly.

Accedere a driver a 16 bit da Linux/i386

Ciò è teoricamente possibile (dimostrazione: guardate come DOSEMU riesca a garantire ai programmi un accesso a porte hardware in modo selettivo), ed ho anche sentito voci secondo le quali qualcuno da qualche parte ci sarebbe di fatto riuscito (nel driver PCI? Roba per l'accesso VESA? ISA PnP? Non so). Se avete informazioni più precise a riguardo, siate i benvenuti. Comunque, buoni posti in cui cercare maggiori informazioni sono i sorgenti del kernel di Linux, i sorgenti di DOSEMU (ed altri programmi nel DOSEMU repository), e sorgenti di vari programmi a basso livello sotto Linux... (forse GGI se supporta VESA). Fondamentalmente, dovete usare la modalità protetta a 16 bit o il modo vm86.

Il primo è più semplice da mettere in piedi, ma funziona solamente con codice «educato» (well-behaved) che non utilizza l'aritmetica dei segmenti o indirizzamento assoluto degli stessi (segmento 0 in particolare), a meno che non ci si trovi nel caso in cui tutti i segmenti utilizzati possano essere preparati in anticipo nella LDT.

Il secondo permette più «compatibilità» con i comuni ambienti a 16 bit, ma richiede una gestione più complessa.

In entrambi i casi, prima di poter saltare al codice a 16 bit, dovete

Ancora una volta, leggete con cura i sorgenti dei contributi al DOSEMU repository menzionato sopra, in particolare quei mini-emulatori per far girare ELKS e/o semplici programmi .COM sotto Linux/i386.

5.2 DOS

La maggior parte dei DOS extender viene fornita con dell'interfacciamento a servizi DOS. Leggete la loro documentazione a riguardo, ma spesso si limitano a simulare int $0x21 e simili, così vi comportate «come se» foste in modo reale (dubito che abbiano qualcosa di più di stub ed estensioni per lavorare con operandi a 32 bit; molto probabilmente si limiteranno a riportare l'interrupt nel gestore del modo reale o del vm86).

Documentazione su DPMI e affini (e molto più) può essere trovata in ftp://x2ftp.oulu.fi/pub/msdos/programming/

Anche DJGPP viene fornito con il proprio derivato/sottoinsieme/sostituto di glibc.

È possibile la compilazione incrociata da Linux a DOS, guardate nella directory devel/msdos/ del vostro mirror locale dell'area FTP di sunsite.unc.edu Date anche un'occhiata al DOS extender «MOSS» dal progetto Flux in Utah.

Altri documenti e FAQ sono molto DOS-centrici. Noi non consigliamo di sviluppare per DOS.

5.3 Winzozz e compagnia bella

Ehi, questo documento riguarda solo il software libero. Telefonatemi quando Winzozz diventa libero, o ci si possono usare strumenti di sviluppo liberi!

Beh, dopotutto ci sono: Cygnus Solutions ha sviluppato la libreria cygwin32.dll per far girare i programmi GNU su piattaforme Micrashoft. Così potete usare GCC, GAS, tutti gli strumenti di GNU e molte altre applicazioni UNIX. Date un'occhiata alla loro homepage. Io (Faré) non intendo dilungarmi sulla programmazione di WinnaNanna ma sono certo che potete trovare un sacco di documentazione a riguardo praticamente ovunque...

5.4 Un sistema operativo tutto vostro.

Essendo il controllo ciò che attrae molti programmatori all'assembly, il desiderio di sviluppare sistemi operativi è spesso ciò che li porta all'(o deriva dall') hacking in assembly. Va notato che ogni sistema che permette lo sviluppo di se stesso potrebbe essere considerato un «sistema operativo», anche se magari gira «sopra» ad un sistema sottostante che fornisce multitasking o I/O (in modo molto simile a Linux sopra Mach o OpenGenera sopra UNIX), ecc.

Quindi, per rendere più facile il debugging, potreste voler sviluppare il vostro «sistema operativo» prima come processo che gira sopra a Linux (nonostante la lentezza), quindi usare il Flux OS kit (che consente l'utilizzo di driver di Linux e BSD nel vostro OS) per renderlo autonomo. Quando il vostro sistema è stabile, resta ancora del tempo per scrivere dei driver per l'hardware tutti vostri, se la cosa vi fa proprio piacere.

Questo HOWTO non si occuperà di argomenti quali il codice per il boot loader ed entrare nel modo a 32 bit, gestire gli interrupt, i fondamenti degli orrori intel «modo protetto» o «V86/R86», la definizione di un vostro formato per i file oggetto e le convenzioni di chiamata. Il luogo principale in cui trovare informazioni attendibili a riguardo sono i sorgenti di sistemi operativi o bootloader già esistenti. Ci sono un sacco di riferimenti in questa pagina WWW: http://www.eleves.ens.fr:8080/home/rideau/Tunes/Review/OSes.html


Avanti Indietro Indice