Faire correspondre les codes Intel à la sortie de désassemblage

Sep 14 2020

Je commence à utiliser la page de référence d'Intel pour rechercher et en savoir plus sur les codes opérationnels (au lieu de tout demander sur SO). Je voudrais m'assurer que ma compréhension est OK et poser quelques questions sur la sortie entre un programme asm de base et les codes d'instructions Intel.

Voici le programme que j'ai pour comparer diverses movinstructions dans le raxregistre -ish (y a-t-il une meilleure façon de dire "rax" et ses composants 32-16 et 8 bits?):

.globl _start
_start:
    movq $1, %rax # move immediate into 8-byte rax (rax) movl $1,    %eax    # move immediate into 4-byte rax (eax)
    movw $1, %ax # move immediate into 2-byte rax (ax) movb $1,    %al     # move immediate into 1-byte rax (al)
    mov $60,    %eax
    syscall

Et il se démonte comme suit:

$ objdump -D file

file:     file format elf64-x86-64


Disassembly of section .text:

0000000000400078 <_start>:

  400078:   48 c7 c0 01 00 00 00    mov    $0x1,%rax 40007f: b8 01 00 00 00 mov $0x1,%eax
  400084:   66 b8 01 00             mov    $0x1,%ax 400088: b0 01 mov $0x1,%al

  40008a:   b8 3c 00 00 00          mov    $0x3c,%eax
  40008f:   0f 05                   syscall

Maintenant, correspondant aux codes Intel de MOV, copiés ici:

Je suis en mesure de concilier les quatre instructions suivantes:

  1. mov $0x1,%al-> b0 01
    OUI , le code des états Intel est b0[+ 1 octet pour la valeur] pour un déplacement immédiat de 1 octet.
  2. mov $0x1,%eax-> b8 01 00 00 00
    OUI , le code des états Intel est b8[+ 4 octets pour la valeur] pour un déplacement immédiat de 1 octet.
  3. mov $0x1,%ax-> 66 b8 01 00
    NON , le code des états Intel b8ne l' est pas 66 b8.
  4. mov $0x1,%rax48-> c7 c0 01 00 00 00
    N / A , instructions 32 bits uniquement. Non listé.

À partir de là, ma question à ce sujet est:

  • Pourquoi le mov $0x1,%axmatch ne fonctionne-t-il pas ?
  • Existe-t-il le même tableau pour les 64codes -bits, ou quelle est la manière suggérée de rechercher cela?
  • Enfin, comment les codes s'ajustent-ils lorsque le registre change? Par exemple, si je souhaite déplacer une valeur vers %ebxou à la %r11place. Comment calculez-vous le 'code-ajustement', comme il ressemble dans cette table de recherche, il ne donne (je pense?) Que le eaxregistre pour les 'codes d'exemple de registre'.

Réponses

3 ChrisDodd Sep 14 2020 at 03:22

Il vous manque le (concept de) préfixe "opcodes" qui change la signification de l'instruction suivante. Le volume 2, sections 2.1.1 et 2.2.1 du manuel IA32 couvre ce sujet. À partir de 2.1.1, nous obtenons:

Le préfixe de remplacement de la taille de l'opérande est codé en utilisant 66H (66H est également utilisé comme préfixe obligatoire pour certaines instructions).

ainsi le préfixe 66 change la taille de l'opérande de 32 bits par défaut à 16 bits. Ainsi, le mov $1,%ax(16 bits) est le même que mov $1,%eax(32 bits) avec juste le préfixe 66

Le dernier cas ( mov $1, %rax) utilise en fait une instruction différente

REX.W + C7 /0 io    MOV r/m64, imm32      Move imm32 sign extended to 64-bits tor/m64.

ici nous déplaçons une constante dans n'importe quel registre au lieu de A - l'instruction est un octet plus grand mais permet de déplacer un 32 bits immergé dans un registre 64 bits, donc n'a besoin que d'une constante de 4 octets au lieu d'un 8 octets un (donc finit par être 3 octets plus petit que l'équivalent 48 b8 01 00 00 00 00 00 00 00)