Encodage d'instructions simples
Prenons les instructions d'assemblage suivantes:
add %cl,%bl
Ceci est encodé comme:, 00 cbou 00000000 11001011en binaire. En mettant le cbdans les champs de bits ModR / M, cela ressemble à:
1 1 0 0 1 0 1 1
+---+---+---+---+---+---+---+---+
| mod | reg | r/m |
+---+---+---+---+---+---+---+---+
Et, en regardant le champ de registre ici, nous obtenons:
- mod:
11(Enregistrer le mode d'adressage) - reg:
001(registre cl) - r / m:
011(registre bl)
Et, je crois que 000000dsc'est l' addinstruction, et d=s=0puisque ce sont tous des registres. Est-ce une compréhension correcte de la façon dont cette instruction est codée? De plus, pour le schéma de `` codage complet '', les éléments suivants seraient-ils précis (en octets et non en bits):
[empty] 0x0 0b11001011 [empty] [empty] [empty]
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
Prefix Instruction Mod-reg-r/m Scale displacement immediate
Y a-t-il des choses qui me manquent ici dans ma tentative de «décoder» l'instruction?
Réponses
Oui, ça a l'air bien.
Le modèle général (pour les instructions ALU "héritées" qui remontent à 8086) pour le codage op r/m, rcontre op r, r/m, et 8 bits contre 16/32 bits utilise les 2 bits bas de l'octet d'opcode dans un modèle régulier, mais ce n'est pas nécessaire se fier à cela.
Intel documente entièrement ce qui se passe pour chaque encodage de chaque instruction dans son manuel vol.2. Voir la colonne Op / En et le tableau de codage des opérandes addpar exemple. (Voir égalementhttps://ref.x86asm.net/coder64.htmqui spécifie également quel opérande est lequel pour chaque opcode). Ceux-ci vous permettent de savoir quels opcodes prennent un octet ModRM et lesquels ne le font pas.
Ceux-ci utilisent bien sûr l'ordre de la syntaxe Intel. Vous vous compliquez la vie en essayant de suivre les manuels et les didacticiels tout en utilisant la syntaxe AT&T qui inverse l'ordre de la liste d'opérandes par rapport aux manuels Intel et AMD.
par exemple, 00 /rest répertorié comme MRencodage d'opérande, qui dans la table que nous pouvons voir est l'opérande 1 = ModRM:r/m (r, w), donc il est lu et écrit, et encodé par le r/mchamp. opérande 2 = ModRM:reg (r), donc c'est une source en lecture seule encodée par le regchamp.
Fait amusant: 00 00est add [rax], al, ou AT&Tadd %al, (%rax)
Notez que vous pouvez demander à GAS de choisir l'un ou l'autre encodage: différences d'opcode x86 XOR
{load} add %cl,%bl # 02 d9
{store} add %cl,%bl # 00 cb
Voir aussi Différence entre MOV r / m8, r8 et MOV r8, r / m8