Intel x86 Assembly Language & Microarchitecture
Assembleurs
Recherche…
Microsoft Assembler - MASM
Étant donné que le 8086/8088 était utilisé sur le PC IBM, et que le système d’exploitation était le plus souvent celui de Microsoft, l’assembleur MASM de Microsoft était la norme de facto pendant de nombreuses années. Il suivait de près la syntaxe d'Intel, mais autorisait une syntaxe pratique mais "souple" qui (avec le recul) ne provoquait que confusion et erreurs de code.
Un exemple parfait est le suivant:
MaxSize EQU 16 ; Define a constant
Symbol DW 0x1234 ; Define a 16-bit WORD called Symbol to hold 0x1234
MOV AX, 10 ; AX now holds 10
MOV BX, MaxSize ; BX now holds 16
MOV CX, Symbol ; ????
La dernière instruction MOV met-elle le contenu de Symbol dans CX ou l' adresse de Symbol dans CX ? Est-ce que CX se retrouve avec 0x1234 ou 0x0102 (ou autre)? Il s'avère que CX se retrouve avec 0x1234 - si vous voulez l’adresse, vous devez utiliser le spécificateur OFFSET
MOV AX, [Symbol] ; Contents of Symbol
MOV CX, OFFSET Symbol ; Address of Symbol
Intel Assembler
Intel a écrit la spécification du langage d'assemblage 8086, dérivé des précédents processeurs 8080, 8008 et 4004. En tant que tel, l'assembleur qu'ils ont écrit a suivi sa propre syntaxe avec précision. Cependant, cet assembleur n'a pas été très utilisé.
Intel a défini ses opcodes pour avoir soit zéro, un ou deux opérandes. Les instructions ont été définies deux opérandes être dans la dest , source de l' ordre, ce qui était différent des autres assembleurs à l'époque. Mais certaines instructions utilisaient des registres implicites comme des opérandes - vous deviez juste savoir ce qu’elles étaient. Intel a également utilisé le concept d'opcodes "prefix" - un opcode affecterait la prochaine instruction.
; Zero operand examples
NOP ; No parameters
CBW ; Convert byte in AL into word in AX
MOVSB ; Move byte pointed to by DS:SI to byte pointed to by ES:DI
; SI and DI are incremented or decremented according to D bit
; Prefix examples
REP MOVSB ; Move number of bytes in CX from DS:SI to ES:DI
; SI and DI are incremented or decremented according to D bit
; One operand examples
NOT AX ; Replace AX with its one's complement
MUL CX ; Multiply AX by CX and put 32-bit result in DX:AX
; Two operand examples
MOV AL, [0x1234] ; Copy the contents of memory location DS:0x1234 into AL register
Intel a également enfreint une convention utilisée par d'autres assembleurs: pour chaque opcode, un mnémonique différent a été inventé. Cela nécessitait des noms différents ou subtilement différents pour des opérations similaires: par exemple, LDM pour "Load from Memory" et LDI pour "Load Immediate". Intel utilisait le seul MOV mnémonique - et attendait de l'assembleur qu'il détermine quel opcode utiliser à partir du contexte. Cela a causé beaucoup de pièges et d'erreurs aux programmeurs dans le futur, lorsque l'assembleur ne pouvait pas comprendre ce que le programmeur voulait réellement ...
AT & T Assembleur - comme
Bien que le 8086 ait été le plus utilisé sur les PC IBM avec Microsoft, plusieurs autres ordinateurs et systèmes d’exploitation l’utilisaient également, notamment Unix. C'était un produit d'AT & T, et Unix fonctionnait déjà sur plusieurs autres architectures. Ces architectures utilisaient une syntaxe d'assemblage plus conventionnelle - en particulier que les instructions à deux opérandes les spécifiaient dans l'ordre source et dest .
Les conventions d'assembleur AT & T ont donc supplanté les conventions dictées par Intel, et un tout nouveau dialecte a été introduit pour la gamme x86:
- Les noms de registre ont été préfixés par
%:
%al,%bxetc. - Les valeurs immédiates ont été préférées par
$:
$4 - Les opérandes étaient à la
source, ordre dedest - Les opcodes incluaient leurs tailles d'opérandes:
movw $4, %ax ; Move word 4 into AX
Borland's Turbo Assembler - TASM
Borland a démarré avec un compilateur Pascal appelé "Turbo Pascal". Cela a été suivi par des compilateurs pour d’autres langages: C / C ++, Prolog et Fortran. Ils ont également produit un assembleur appelé "Turbo Assembler", qui, selon la convention de dénomination de Microsoft, s'appelait "TASM".
TASM a tenté de résoudre certains problèmes d'écriture de code en utilisant MASM (voir ci-dessus), en fournissant une interprétation plus stricte du code source sous un mode IDEAL spécifié. Par défaut, il supposait le mode MASM , donc il pouvait assembler le source MASM directement - mais Borland a ensuite trouvé qu'il devait être compatible avec le bogue avec les particularités plus "bizarres" du MASM - ainsi ils ont ajouté un mode QUIRKS .
Étant donné que TASM était (beaucoup) moins cher que MASM, il disposait d’une large base d’utilisateurs, mais peu de gens utilisaient le mode IDEAL, malgré ses avantages vantés.
Assembleur GNU - gaz
Lorsque le projet GNU avait besoin d'un assembleur pour la famille x86, ils utilisaient la version AT & T (et sa syntaxe) associée à Unix plutôt qu'à la version Intel / Microsoft.
Netwide Assembler - NASM
NASM est de loin l'assembleur le plus porté pour l'architecture x86 - il est disponible sur pratiquement tous les systèmes d'exploitation basés sur le x86 (même s'il est inclus avec MacOS) et est disponible en tant qu'assembleur multiplateforme sur d'autres plates-formes.
Cet assembleur utilise la syntaxe Intel, mais il est différent des autres car il se concentre fortement sur son propre langage "macro". Cela permet au programmeur de construire des expressions plus complexes en utilisant des définitions plus simples, permettant de créer de nouvelles "instructions".
Malheureusement, cette fonctionnalité puissante a un coût: le type de données gêne les instructions généralisées, de sorte que le typage des données n'est pas appliqué.
response: db 'Y' ; Character that user typed
cmp response, 'N' ; *** Error! Unknown size!
cmp byte response, 'N' ; That's better!
cmp response, ax ; No error!
Cependant, la NASM a introduit une fonctionnalité qui manquait à d'autres: des noms de symboles définis. Lorsque vous définissez un symbole dans d'autres assembleurs, ce nom est disponible dans le reste du code - mais il "utilise" ce nom, "polluant" l'espace de nom global avec des symboles.
Par exemple (en utilisant la syntaxe NASM):
STRUC Point
X resw 1
Y resw 1
ENDSTRUC
Après cette définition, X et Y sont définis pour toujours. Pour éviter d’utiliser les noms X et Y , vous devez utiliser des noms plus précis:
STRUC Point
Pt_X resw 1
Pt_Y resw 1
ENDSTRUC
Mais la NASM offre une alternative. En exploitant son concept de "variable locale", vous pouvez définir des champs de structure vous obligeant à nommer la structure contenant dans les futures références:
STRUC Point
.X resw 1
.Y resw 1
ENDSTRUC
Cursor ISTRUC Point
ENDISTRUC
mov ax,[Cursor+Point.X]
mov dx,[Cursor+Point.Y]
Malheureusement, comme NASM ne garde pas trace des types, vous ne pouvez pas utiliser la syntaxe la plus naturelle:
mov ax,[Cursor.X]
mov dx,[Cursor.Y]
Encore un autre assembleur - YASM
YASM est une réécriture complète de NASM, mais est compatible avec les syntaxes Intel et AT & T.