Combinando os códigos intel com a saída de desmontagem

Sep 14 2020

Estou começando a usar a página de referência da Intel para pesquisar e aprender sobre os códigos operacionais (em vez de perguntar tudo sobre SO). Gostaria de ter certeza de que meu entendimento está OK e fazer algumas perguntas sobre a saída entre um programa asm básico e os códigos de instrução intel.

Aqui está o programa que eu tenho para comparar várias movinstruções no raxregistro -ish (há uma maneira melhor de dizer "rax" e seus componentes de 32-16- e 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

E ele se desmonta da seguinte forma:

$ 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

Agora, combinando com os códigos intel de MOV, copiados aqui:

Sou capaz de conciliar o seguinte das quatro instruções:

  1. mov $0x1,%al-> b0 01
    SIM , o código de estados intel é b0[+ 1 byte para valor] para movimentação imediata de 1 byte.
  2. mov $0x1,%eax-> b8 01 00 00 00
    SIM , o código dos estados da inteligência é b8[+ 4 bytes para o valor] para movimentação imediata de 1 byte.
  3. mov $0x1,%ax-> 66 b8 01 00
    NÃO , o código dos estados da Intel b8não é 66 b8.
  4. mov $0x1,%rax48-> c7 c0 01 00 00 00
    N / A , apenas instruções de 32 bits. Não listado.

A partir disso, minhas perguntas relacionadas a isso são:

  • Por que não mov $0x1,%axcombina?
  • Existe a mesma tabela para 64códigos de bits, ou qual é a maneira sugerida de pesquisar isso?
  • Finalmente, como os códigos se ajustam quando o registro muda? Por exemplo, se eu quiser mover um valor para %ebxou em %r11vez disso. Como você calcula o 'ajuste de código', visto que nesta tabela de pesquisa ela apenas dá (eu acho?) O eaxregistro para os 'códigos de exemplo de registro'.

Respostas

3 ChrisDodd Sep 14 2020 at 03:22

Está faltando o (conceito de) prefixo "opcodes" que muda o significado da instrução a seguir. O Volume 2, seções 2.1.1 e 2.2.1 do manual IA32 cobre isso. De 2.1.1 obtemos:

O prefixo de substituição do tamanho do operando é codificado usando 66H (66H também é usado como um prefixo obrigatório para algumas instruções).

portanto, o prefixo 66 altera o tamanho do operando do padrão de 32 bits para 16 bits. Assim, o mov $1,%ax(16 bits) é o mesmo que mov $1,%eax(32 bits) com apenas o prefixo 66

O último caso ( mov $1, %rax) está realmente usando uma instrução diferente

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

aqui, estamos movendo uma constante para qualquer registro em vez de A - a instrução é um byte maior, mas permite mover um registro de 32 bits para um registro de 64 bits, então só precisa de uma constante de 4 bytes em vez de 8 bytes um (então acaba sendo 3 bytes menor que o equivalente 48 b8 01 00 00 00 00 00 00 00 00)