Domanda

Spero di imparare il linguaggio assembly per x86. Sono su un Mac, e sto assumendo la maggior parte dei tutorial x86 / libri utilizzare il codice che è destinata per Windows.

In che modo il sistema operativo che il codice viene eseguito sul influenzano ciò che fa il codice, o determinare se il codice funziona ancora? Potrei seguire un tutorial basato su Windows, e modificare alcuni comandi per farlo funzionare per Mac con relativa facilità? Più in generale, c'è qualcosa difficile che un programmatore di assemblaggio Mac, in particolare, dovrebbe sapere? Grazie!

È stato utile?

Soluzione

(Naturalmente, tutti i seguenti vale solo per x86 e x86-64 linguaggio assembly, per IA-32 e AMD64 processori e sistemi operativi.)

Le altre risposte attualmente visibile sono tutti corretti, ma, a mio parere, manca il punto. AT & T contro la sintassi Intel è un non-problema completo; qualsiasi strumento decente lavorerà con entrambe le sintassi o di avere una controparte o la sostituzione che fa. E si riuniscono lo stesso in ogni caso. (Protip: si vuole veramente utilizzare la sintassi Intel Tutta la documentazione ufficiale del processore fa sintassi AT & T è solo un mal di testa gigante...) Sì, trovando le bandiere giuste per passare al assemblatore e linker può essere difficile, ma potrai sapere quando hai capito e hai solo di farlo una volta per ogni sistema operativo (se vi ricordate di scriverlo da qualche parte!).

Istruzioni di montaggio stessi, naturalmente, sono completamente OS-agnostico. La CPU non si preoccupa quale sistema operativo è in esecuzione. A meno che non si sta facendo estremamente basso livello aggiustamenti (vale a dire, lo sviluppo del sistema operativo), i dadi e bulloni di come il sistema operativo e interagiscono CPU sono quasi del tutto irrilevante.

Il mondo esterno

Il problema di linguaggio assembly arriva quando si interagisce con il mondo esterno: il kernel del sistema operativo, e altro codice userspace. Userspace è più difficile: si deve ottenere il giusto ABI o il vostro programma di montaggio, ma è tutto inutile. Questa parte non è in genere portabile tra sistemi operativi a meno che non si utilizza trampolini / thunk (in pratica un altro strato di astrazione che deve essere riscritto per ogni sistema operativo che si intende sostenere).

La parte più importante della ABI è qualunque sia la convenzione di chiamata per le funzioni in stile C. Sono quelli che vengono più comunemente supportati, e quello che probabilmente stai andando ad essere l'interfacciamento con se si sta scrivendo il montaggio. Agner Fog mantiene diversi buone risorse su suo sito ; le href="http://www.agner.org/optimize/calling_conventions.pdf" descrizione dettagliata di convenzioni di chiamata è particolarmente utile. Nella sua risposta, Norman Ramsey cita PIC e librerie dinamiche; nella mia esperienza di solito non c'è bisogno di perdere tempo con coloro che se non si vuole. linking statico funziona bene per gli usi tipici del linguaggio assembly (come riscrittura funzioni principali di un ciclo interno o altro hotspot).

La convenzione di chiamata funziona in due direzioni: è possibile chiamare da C di montaggio o di montaggio da C. Quest'ultimo tende ad essere un po 'più facile, ma non c'è una grande differenza. Chiamata C dal montaggio consente di utilizzare le cose come le funzioni di uscita libreria standard C, mentre chiama assembly da C è in genere come si accede un'implementazione montaggio di una singola funzione delle prestazioni critiche.

chiamate di sistema

L'altra cosa il vostro programma farà è effettuare chiamate di sistema. È possibile scrivere un programma completo e utile di assemblaggio che non chiama mai le funzioni C esterni, ma se si vuole scrivere un programma di puro linguaggio assembly che non esternalizzare il divertenti per il codice di qualcun altro, si sta andando a necessità chiamate di sistema. E, purtroppo, le chiamate di sistema sono totalmente e completamente diversa per ogni sistema operativo. Sistema in stile Unix chiamate è necessario includere (ma sono quasi sicuramente non limitato a!) open, creat, read, write, e il exit tutto-importante, insieme a mmap se vi piace l'allocazione della memoria in modo dinamico.

Mentre ogni sistema operativo è diverso, la maggior parte dei sistemi operativi moderni seguono un modello generale: si carica il numero del sistema di chiamata che si desidera in un registro, in genere EAX in codice a 32 bit, quindi caricare i parametri (come si fa che varia selvaggiamente ), e, infine, emettere una richiesta di interruzione: è INT 2E per i kernel di Windows NT o INT 80h per 2.xe Linux e FreeBSD (e, credo, OSX). Il kernel prende poi sopra, esegue la chiamata di sistema, e restituisce executione al vostro programma. A seconda del sistema operativo, potrebbe cestino registri o stack come parte della chiamata di sistema; si dovrà fare in modo di leggere la documentazione chiamata di sistema per la piattaforma per essere sicuri.

SYSENTER

Linux kernel 2.6 (e, credo, Windows XP e versioni successive, se non ho mai realmente tentato su Windows) anche il supporto di un metodo più nuovo più veloce per effettuare una chiamata di sistema: l'istruzione SYSENTER introdotto da Intel nel chip Pentium più recenti . chip AMD hanno SYSCALL, ma alcuni sistemi operativi a 32-bit usano (anche se è lo standard a 64 bit, penso, non ho dovuto fare sistema direttamente chiamate da un programma a 64 bit, quindi non sono sicuro su questo ). SYSENTER è significativamente più complicato da configurare e utilizzare (vedi, ad esempio, Linus Torvalds sull'attuazione SYSENTER supporto per Linux 2.6 : "sono un porco schifoso, e fiero di esserlo per l'avvio"). personalmente posso attestare la sua peculiarità; Una volta ho scritto una funzione di montaggio che ha emesso SYSENTER direttamente ad un kernel Linux 2.6, e I ancora non capiscono i vari stack e registrarsi trucchi che ricevuti farlo funzionare ... ma lavoro lo ha fatto!

SYSENTER è un po 'più veloce di emissione INT 80h, e quindi il suo utilizzo è desiderabile quando disponibili. Per rendere più facile scrivere sia il codice veloce e portatile, Linux mappa una VDSO chiamato linux-gate nello spazio degli indirizzi di ogni programma; chiamare una funzione speciale in questo VDSO emetterà una chiamata di sistema dal meccanismo più veloce disponibile. Purtroppo, utilizzando in genere è più problemi che ne vale la pena: INT 80h è molto più semplice da fare in una piccola routine di assembly che vale la pena il piccolo rigore velocità. A meno che non hai bisogno di massime prestazioni ... e se avete bisogno che, probabilmente non si desidera chiamare in un VDSO ogni caso, e sai che il tuo hardware, quindi si può solo fare la cosa terribilmente pericoloso e problema SYSENTER te stesso.

Altro

Oltre alle richieste imposte interagendo con il kernel e altri programmi, ci sono molto, molto poche differenze tra i sistemi operativi. Assemblea espone l'anima della macchina: si può lavorare come ti piace, e dentro il proprio codice che non sono vincolati da alcuna particolare convenzione di chiamata. Potrete accedere gratuitamente alle unità FPU e SSE; si può PREFETCH direttamente per lo streaming di dati dalla memoria nella cache L1 e assicurarsi che sia caldo per quando ne avete bisogno; è possibile munge la pila a volontà; è possibile emettere INT 3 se si vuole interfacciare con un (correttamente configurato;! buona fortuna) debugger esterno. Nessuna di queste cose dipendono dal sistema operativo. L'unica vera limitazione che hai è che si esegue al Ring 3, non Ring 0, e così alcuni registri di controllo del processore non saranno disponibili a voi. (Ma se avete bisogno di quelli, si sta scrivendo il codice del sistema operativo, non il codice di applicazione.) Oltre a questo, la macchina è messo a nudo per voi: andate avanti e calcolare

Altri suggerimenti

In generale, fino a quando si utilizza lo stesso assemblatore, e la stessa architettura (per esempio, NASM, e x86-64), si dovrebbe essere in grado di assemblare il montaggio sia su Windows e Mac.

Tuttavia, è importante tenere a mente che i formati eseguibili e gli ambienti di esecuzione possono essere diverse. Come esempio, Windows potrebbe emulare / gestire alcune istruzioni privilegiate in modo diverso per Mac, causando un comportamento diverso.

anche una grande parte della differenza è nel modo in cui il programma comunica con il mondo esterno.

Per esempio, se si desidera visualizzare un messaggio all'utente o leggere un file o allocare più memoria dovete chiedere il sistema operativo di farlo, facendo una sorta di chiamata di sistema. che ti essere molto differenti tra sistemi operativi.

La sintassi del linguaggio stesso dovrebbe essere sostanzialmente identico fino a quando si sta utilizzando lo stesso assemblatore. Diversi assemblatori a volte hanno ordinamento leggermente diverso sulla sintassi o le diverse macro ma niente che è troppo difficile abituarsi.

The Great Divide in linguaggio assembly Intel è tra sintassi AT & T e la sintassi Intel. Vorrete un assemblatore per il vostro Mac che utilizza la stessa sintassi dei tutorial che si usa. Poiché credo MacOS Darwin, una variante BSD, utilizza la sintassi AT & T, e l'assemblatore Microsoft utilizza la sintassi Intel, è necessario stare attenti.

L'altra differenza di attenzione è Application Binary Interface del sistema (ABI), che copre convenzioni di chiamata, il layout dello stack, chiamate di sistema, e così via. Essi possono differire in modo sostanziale tra i sistemi operativi, in particolare quando si tratta di codice indipendente dalla posizione e il collegamento dinamico . Ho ricordi vaghi infelici che PIC è stata particolarmente complicata sulla PowerPC MacOS, ma forse è più semplice sul processore Intel.

Un pezzo di consigli:. imparare x86_64 (noto anche come AMD64) -è molto più divertente da scrivere codice assembly a mano, e sarete più a prova di futuro

Quando ho immerso in Assemblea durante una delle mie di programmazione turistica visite, il Gotcha che mi ha sostenuto in ogni tutorial non è stato in grado di compilare in formato binario corretto. La maggior parte dei tutorial danno elf (per Linux) e aoutb (per BSD), ma con quest'ultimo OS X si lamenta (scelta logica?):

ld: hello.o bad magic number (not a Mach-O file)

ancora Mach-O fallisce come formato, e se si man nasm si ottiene solo bin, formati aout e di file elf - man ld non è più disponibile - macho è l'opzione per rendere il formato di Mach-O per OS X:

nasm -f macho hello.asm

I scritto il viaggio qui (include un link ad un bel fascio TextMate per il montaggio e altre informazioni), ma - di essere breve -. è possibile che questo è ciò che serve per iniziare

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top