Combinando os códigos intel com a saída de desmontagem
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:
mov $0x1,%al->b0 01
SIM , o código de estados intel éb0[+ 1 byte para valor] para movimentação imediata de 1 byte.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.mov $0x1,%ax->66 b8 01 00
NÃO , o código dos estados da Intelb8não é66 b8.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?) Oeaxregistro para os 'códigos de exemplo de registro'.
Respostas
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)