From: "valerio" <valerio_ligabue@xxxxxxxxx> Subject: [prog-it] Re: porta seriale Date: Wed, 29 May 2002 00:15:43 +0200 | Ecco, hai proprio centrato il problema. | Dove trovo documentazione a tale proposito ? | Tenendo presente che il mio inglese e` una pena. La documentazione migliore, non so se purtroppo o per fortuna per te, sono i sorgenti del kernel Linux. | Ho un minimo di esperienza con l'assembler Purtroppo programmare in assembler su sistemi GNU/ Linux non e' la cosa piu' facile del mondo; sono sistemi a 32 bit shared-library in modalita' protetta e gia' questo ti dovrebbe far pensare che non puoi utilizzare interrupt. In realta' c'e' un interrupt che puoi utilizzare ed e' l'INT 80h con chiamate a basso livello al kernel (in unistd.h trovi tutte le chiamate possibili); praticamente e' un "portale" per le syscall. Utilizzando l'INT 80h, il registro "eax" deve contenere il numero della funzione che richiami. I parametri che devi passare alla funzione in oggetto devi inserirli nei seguenti registri (rispetta l'ordine): "ebx", "ecx", "edx", "esi", "edi" Da questo ne deduci che il primo parametro si trova in "ebx", il secondo in "ecx" e cosi' via (utilizzando registri puoi notare che non si usa lo stack per passare i parametri). Infine il valore restituito dalla funzione lo troverai in "eax". Cmq l'assembly sotto linux ha anche l'innegabile vantaggio di permetterti di richiamare funzioni delle librerie standard C; un vantaggio, secondo me, non da poco (qui si aprono delle problematiche, se vogliamo chiamarle cosi', di gestione dello stack alla C, con tutto quello che ne consegue). Esistono vari assemblatori in sistemi GNU/Linux, ma i due piu' utilizzati sono Nasm di Netwide, e GAS di Gnu che e' integrato direttamente in GCC. Il mio personale consiglio e' di utilizzare, almeno all'inizio, Nasm, poiche' GAS utilizza la sintassi AT&T; le diversita' piu' grosse, in breve, sono: * Nei "movimenti", la sorgente viene prima della destinazione. * Al termine dell'opcode viene suffissa una lettera indicante il formato degli operandi ("l" = dword, "w" = word, "b" = byte). * Numeri che devono essere interpretati come valori immediati, devono avere, come prefisso, "$", mentre i registri devono essere preceduti da "%". * Gli indirizzamneti effettivi seguono la sintassi: DISP(BASE,INDEX,SCALE). Ci sono molte altre piccole differenze, come il fatto che in GAS si marca con un "*" un valore assoluto, mentre nella sintassi Intel non viene fatto; il fatto che in GAS non esiste la keyword "FAR"; in virtu' di questo fatto devi prefissare la call o il jump con una "l", in modo da trasformare una "far call" in una "lcall" o un "far jmp" in un "ljmp" o una "ret far" in "lret", ecc. ecc. Come esempio generale ti posso fare questo, che piu' o meno riassume tutte le differenze; cio' che nella sintassi intel si scrive: MOV eax, [eax + ecx*4 + indirizzo] con GAS diventa: movl indirizzo(%ebx, %ecx, 4), %eax In virtu' di cio', se gia' hai esperienze di programmazione in assembler su piattaforme x86 in DOS, ti riconsiglio di utilizzare il Nasm che dovrai richiamare con il flag di formato ELF attivato "nasm -f elf valerio.asm"; il file object cosi' creato dovrai poi linkarlo con GCC "gcc valerio.o" per ottenere, finalmente, il sospirato file ELF eseguibile. Per il tuo problema, in particolare, per avere un accesso diretto all'hardware, nei sistemi GNU/Linux hai bisogno di un "driver" kernel-mode; l'accesso diretto alle porte I/O deve essere concesso dal sistema operativo; a tal scopo devi effettuare una chiamata a ioperm(). Questa funzione puo' essere chiamata solo da root, quindi o setuid il programma oppure lo esegui direttamente da super-user. Una volta conclusa la chiamata a ioperm() potrai accedere alle porte desiderate come utente normale. Un'ulteriore fonte di informazione che ti posso consigliare e' il man del Nasm e quello del GAS, e ti ripropongo i sorgenti del kernel Linux. | Per ora grazie di tutto. Figurati. Alla prossima. Ciao. -- Lo sporco costituisce il 90 per cento di tutto.