-
Notifications
You must be signed in to change notification settings - Fork 16
/
Copy pathx86_General.language.txt
283 lines (260 loc) · 17.5 KB
/
x86_General.language.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
┏━━━━━━━━━━━━━━━━━┓
┃ X86 GENERAL ┃
┗━━━━━━━━━━━━━━━━━┛
┌─────────────┐
│ GENERAL │
└─────────────┘
Autre nom de x86 : i386
Assemblage : traduit le fichier texte ASM en instruction binaire.
Extension d'un fichier ASM : .S ou .s
1 instruction = nombre variable de cycles de l'horloge. Dépend de :
- la microarchitecure
- l'opérande (R, S, M ou I) (M est le plus lent)
- pour une même microarchitecure donnée, cela peut varier entre deux instants donnés : par exemple avec les out-of-order exécutions (instructions exécutées parallèlement grâce à des queues)
La taille des instructions x86 est variable.
Les M sont plus lents, car il y a accès à la mémoire. Le MMU gère-t-il seulement l'utilisation de M ?
V et M sont inconnus :
- V est assigné run-time (par le linker ?)
- M dépend de l'état actuel de la mémoire. Ainsi, c'est le contenu variable/dynamique d'un programme : un M pointant vers un fichier dépendera par exemple de l'exécution de ce fichier lors du run-time, ce qui inclue stdin et donc les inputs de l'utilisateur.
Différence entre :
- instruction set (ISA, instruction set architecture) (registres, instructions, data types, etc.) :
- comme une interface pour la programmation en ASM
- microarchitecure :
- l'implémentation de cet instruction set dans le CPU
- par exemple, AMD Athlon et Intel Pentium ont tous deux des CPU partageant le même ISA (x86), mais en interne, le CPU marche différemment, même si pour le développeur ASM, c'est la même chose.
0 portabilité : le langage ASM dépend du CPU, et les interruptions de l'OS
┌────────────────────────────┐
│ DIFFERENTS ASSEMBLEURS │
└────────────────────────────┘
Liste d'assembleurs :
+-------+------+--------+---------+--------------+-----------------------+
| NOM | LIBR | SYNTAX | OS | COMPILATEUR | NOTES |
+-------+------+--------+---------+--------------+-----------------------+
| GAS | y | AT&T | Tous | gcc | Supporte aussi Intel |
| | | | | | syntaxe via directive |
| | | | | | .intel_syntax |
| NASM | y | Intel | Tous | | |
| YASM | y |Int+AT&T| Tous | | Réécriture de NASM |
| FASM | y | Intel | Tous | | |
+-------+------+--------+---------+--------------+-----------------------+
| MASM | n | Intel | Windows | VisualStudio | M$ |
| TASM | n | Intel | Windows | Borland | proche de MASM |
| WASM | n | Intel | Windows | OpenWatcom | |
| JWASM | n | Intel | Tous | | dérivé de WASM, |
| | | | | | compatible avec MASM |
+-------+------+--------+---------+--------------+-----------------------+
En plus de la syntaxe générale, chaque assembleur utilise des syntaxes particulières, par exemple pour définir les variables, les macros, sections, etc.
Du coup, même en définissant au début d'un fichier ASM : .define intel_syntax noprefix, la suite du code, si prévu pour NASM, échouera avec GAS.
┌─────────────────────────────┐
│ DIFFERENTES GENERATIONS │
└─────────────────────────────┘
De nombreuses évolutions récentes ont pour but d'introduire un parallélisme (plusieurs instructions exécutées lors d'un même cycle) au niveau de la microarchitecture du CPU :
- pipelining, superscalar, out-of-order, register renaming, speculative execution
Différentes générations de CPU x86, puis x86_64 :
- P1 à P9 :
- P1 (1978) :
- Intel 8086, 8088, 80186, 80188, NEC V20/V30
- 16 bits registers
- P2 (1982) :
- Intel 80286
- début de protected mode, et MMU, avec 80286
- P3 (1985) :
- Intel 80386, AMD Am386
- 32 bits registres, paging
- P4 (1989) :
- Intel486, AMD Am486/Am5x86
- FPU (x87), cache CPU L1, pipelining
- P5 (1993) :
- Pentium, PentiumMMX, Cyrix 5x86, Rise mP6
- faster FPU, MMX, superscalar
- P6/i636 (1995) :
- PentiumPro, Cyric 6x86, Cyrix MII/III
- cmov*, PAE, CPU Cache L2, out-of-order, speculative execution, register renaming
- P6/i636 (1997) :
- AMD K6, AMD-2/3, Pentium II/III
- CPU Cache L3, 3DNow!, SSE1
- P7 (1999) :
- Athlon
- P7 (2000) :
- Pentium 4
- SSE2, more pipelining, Hyper-T, VT-X
- P8 (2003) :
- Althlon 64, Opteron
- x86_64
- P8 (2004) :
- Pentium 4 prescott
- more pipelining, SSE3
- P8 (2006) :
- Intel Core 2
- multi-core, SSE4.1
- P8 (2007/2008) :
- AMD Phenom, Intel Core i3/i5/i7, Intel Atom
- quad-core, SSE4.2, CPU Cache L3, SSSE3, SMX, VMX
- P9 (2011) :
- Intel Sandy Bridge/Ivy Bridge, AMD Bulldozer/Trinity
- SSE5/AVX, GPU intégré, AES-NI, CLMUL
- P10 (à venir) :
- Intel Larrabee
cpuid :
- valide seulement si l'ID flag == 1
- dépend de eax (parfois ecx aussi)
- modifie eax, ebx, ecx et edx
- eax possibles dépend de l'architecture : ARCH désigne l'architecture minimale
+-----------+--------------+--------------+--------------+--------------+------+
| EAX INPUT | EAX | EBX | ECX | EDX | ARCH |
+-----------+--------------+--------------+--------------+--------------+------+
| 0x0 | eax max pour| Vendor Indentification String | P4/P5|
| |cpuid (max : | (ebx,edx,ecx). Ex: "GeniuneIntel" | |
| | 0xa) | | |
| 0x1 | Version info:| Octet : | Indique les | Indique les | P4/P5|
| | Bits : |- 0 : | supports. | supports. | |
| |- 0x0 à 0x3 : | index dans la| Bits : | Bits : | |
| |Stepping ID | brand string |- 0 : SSE3 |- 0 : x87 | |
| |- 0x4 à 0x7 : | table(cf doc)|- 3 : monitor |- 1 : Virtual | |
| | Model ID |- 1 : |- 4 : DS-CPL | 8086 mode | |
| |- 0x8 à 0x11 :| taille du |- 5 : VMX |- 2 : debug | |
| | Family ID | cache pour |- 7 : EST | fonctions | |
| |- 0x12 à 0x13:| clflush |- 8 : TM2 |- 3 : pages de| |
| |Processor Type|- 2 : réservé |- 9 : SSSE3 | 4Mo possibles| |
| | 0 : OEM |- 3 : |- 0xa: CNXT-ID|- 4 : rdtsc | |
| | 1 : OverDrive| ID du local |- 0xd: |- 5 : rdmsr, | |
| | 2 : Dual | APIC | cmpxchg16b | wrmsr | |
| | 3 : réservé | |- 0xe: xTPR |- 6 : PAE | |
| |- 0x16 à 0x19:| |- 0x10: PDCM |- 7 : MCE | |
| |Ext.Model ID | |- Autres : |- 8: cmpxchg8b| |
| |(si Family ID | | réservés |- 9 : APIC | |
| |== 0x6 ou 0xf)| | |- 0xb:sysexit,| |
| |- 0x20 à 0x27:| | | sysenter | |
| |(si Family ID | | |- 0xc: MTRR | |
| | == 0xf) | | |(type de MSR) | |
| |Ext.Family ID | | |- 0xd: PGE | |
| | | | |- 0xe : MCA | |
| | | | |- 0xf : cmov* | |
| | | | | et fcmov* | |
| | | | |- 0x10 : PAT | |
| | | | |- 0x11: PSE-36| |
| | | | |- 0x12: PSN | |
| | | | |- 0x13: clfush| |
| | | | |- 0x15: DS | |
| | | | |- 0x16: ACPI | |
| | | | |- 0x17: MMX | |
| | | | |- 0x18: fxsave| |
| | | | | fxrstor | |
| | | | |- 0x19 : sse | |
| | | | |- 0x1a : sse2 | |
| | | | |- 0x1b : SS | |
| | | | |- 0x1c : multi| |
| | | | | threading | |
| | | | |- 0x1d : TM | |
| | | | |- 0x1f : PBE | |
| | | | | | |
| 0x2 | Donne infos sur les caches. | P6 |
| | Octet 0 d'eax donne le nombre de fois que cpuid doit être | |
| | exécuté pour pouvoir remplir tous les registres. | |
| | Bit 31 de chaque registre indique si son contenu est valid| |
| | Chaque octet des 4 registres (sauf octet 0 d'eax) | |
| | décrit ensuite un cache : son type (Instruction TLB, | |
| | Data TLB, Instruction Cache L1, Data Cache L1, Cache L2, | |
| | Cache L3, Trace cache, prefetching, Pas de cache L2, Pas | |
| | de cache L2) et : | |
| | Pour tous : | |
| | - nombre de "way set associatives" (1 à 16) | |
| | Pour les TLB : | |
| | - taille pages (4Ko, 2Mo ou 4mo) | |
| | - nombre d'entrées (2 à 256) | |
| | Pour les cache : | |
| | - taille (8Ko à 8Mo) | |
| | - line size (32 à 64) | |
| | - nombre lignes par secteur (1 à 2) | |
| | Pour les trace cache : | |
| | - taille pour les micro-ops (12 à 32Ko) | |
| | Pour le prefetching : | |
| | - taille (64 à 128 octets) | |
| | 0x00 indique "rien à signaler" | |
| | Cf documentation Intel pour précisions sur comment | |
| | interpréter les valeurs. | |
| 0x4 | Infos sur les caches | P7 |
| 0x5 | Information sur les instructions monitor et mwait | P7 |
| 0x6 | Information sur le thermal et power management | P8 |
| 0xa | Information sur le performance monitoring capabilities | P8 |
+-----------+--------------+--------------+--------------+--------------+------+
| 0x8000000 | eax maximal | réservé | réservé | réservé | P6 |
| | pour cpuid | | | | |
| |(max:0x8000008)| | | | |
| 0x8000001 | Extended Proc| | Bit 0 : lahf/| Bit 29 : 64 | P6 |
| | Signature | | sahf 64 bits | bits mode | |
| 0x8000002 | Met dans les registres les 16 premières lettres de la | P6 |
| | brand du CPU (inclue sa fréquence) | | |
| 0x8000003 | Met dans les registres les 16 lettres suivantes | P6 |
| 0x8000004 | Met dans les registres les 16 lettres suivantes | P6 |
| 0x8000006 | Infos sur les caches | | | P7 |
| 0x8000008 | Octet 0 : | | | | P7 |
| | Phys.Adr.Size| | | | |
| | Octet 1 : | | | | |
| | Virt.Adr.Size| | | | |
+-----------+--------------+--------------+--------------+--------------+------+
┌───────────┐
│ MODES │
└───────────┘
x86 ("IA-32") :
- Real mode :
- mode "historique"
- un CPU x86 (ou x86_64) commence toujours en real mode, pour des raisons de rétro-compatibilité.
- Protected mode :
- mode "normal" avec segmentation, pagination, etc.
- V86 (Virtual 8086) mode :
- permet l'émulation de programme conçus pour 8086 (inutile aujourd'hui)
- activé si flag VM d'eflags est activé
- System management mode (SMM) :
- activé via interruption 0x02 (SMI) :
- provoque un dump de l'état courant
- retour de ce mode via l'instruction rsm :
- si précédent dump est incorrect, shutdown du système
- switch vers un adress space spécial, le SMRAM (System Management RAM)
- segmentation et adressing similaire au real-mode
- permet à un OS d'implémenter des choses par rapport à la sécurité, au power management, etc.
Passer de "IA-32" à "IA-32e" -> être en protected mode et activer le bit LMR du MSR IA32_EFER
x86_64 ("IA-32e"):
- Compatibility mode :
- similaire à protected mode 32 bits, permet d'exécuter du code 32 bits, mais pas du code 64 bits.
- Est appliqué code segment par code segment => un OS 64 bits peut le lancer seulement pour les applis 32 bits.
- c'est le bit-L du segment descriptor du code segment qui indique si l'on est en compatibility mode ou non
- 64 bit-mode / long mode :
- permet d'exécuter du code 64 bits. Est aussi appliqué code segment par code segment.
┌───────────────┐
│ REAL MODE │
└───────────────┘
Différences avec protected mode :
- segmentation :
- tout est en 16 bits, non en 32 : pas de eax, etc.
- OFFSET est bits aussi
- Si SEGMENT:OFFSET, adresse linéaire = SEGMENT << 4 + OFFSET, soit adresse de 20 bits maximal (1Mo adressable)
- les interruptions liées au BIOS s'attendent à ce qu'on soit en real mode. Les utiliser sinon peut poser des problèmes.
- instructions indisponibles : verr, verw, lar, lsl, ltr, str, lldt, sldt
- pas de pagination ?
- IDT contient des IDTE de 4 octets, ne contenant que l'adresse vers laquelle effectuer un far jmp. Une interruption push cs:ip sur le stack, et doit être quitté avec iret.
Switcher en protected mode :
- activer le PE-bit de cr0
- doit être suivi d'un jmp pour vider le cache des instructions
Retourner en real mode :
- désactiver le PE-bit de cr0. Pour ce faire :
1) Si paging :
a) faire en sorte que les adresses linéaires == adresses physiques courantes ("identity mapping")
b) désactiver le PG-bit de cr0
c) cr3 = 0, afin de vider le paging cache
2) sauter vers une instruction dont le segment a une limite de 64K, afin que cs ait une bonne limite
3) charger ss, ds, es, fs et gs avec des sélectors :
- ayant une limite de 0xffff
- un G-bit de 0, un Expand-bit de 0, un Writable-bit de 1, un Present-bit de 1
- n'importe quelle BASE
4) disable interrupts via cli.
5) désactiver le PE-bit de cr0
6) jmp vers le real mode code à exécuter (permet de flush l'instruction cache et mettre le bon CPL dans cs)
7) utiliser lidt pour mettre à jour l'IDTR
8) enable interrupts via sti
┌──────────────────┐
│ COPROCESSEUR │
└──────────────────┘
wait : attend que le x87 ait fini son instruction courante (s'il y en a une), et invoque l'exception 0x10 si une erreur a eu lieu, ce qui permet d'émuler de manière logicielle les erreurs x87.
ESC : pas une instruction, mais le pattern de 5 bits (11011b) (opcode 0xd8 à 0xdf donc) au début de toute instruction x87, et qui indique que le coprocesseur doit être utilisé
Lors d'une instruction x87, si MP-bit et TS-bit sont activés, lance une exception 0x07 afin de mettre à jour l'état du coprocesseur.