1 pontos por GN⁺ 2024-07-11 | 1 comentários | Compartilhar no WhatsApp

Coisas estranhas que aprendi ao escrever um emulador x86

  • Explica várias curiosidades e coisas estranhas aprendidas ao escrever emuladores x86 e amd64
  • No Time Travel Debugging (TTD), um emulador de CPU é usado para registrar a execução de um processo no nível de instruções
  • A primeira versão do TTD era chamada de iDNA, foi escrita em Assembly, era rápida, mas difícil de manter
  • A segunda versão foi escrita em C++, melhorando a manutenibilidade

Curiosidades inúteis de codificação x86

  • O esquema de codificação do x86 pode codificar a mesma instrução de várias maneiras
  • A instrução int 3 pode ser codificada como CD 03 ou CC
  • O registrador EAX é chamado de "registrador acumulador" e isso realmente faz diferença na codificação
  • O prefixo REX permite acessar uma faixa mais ampla de registradores em código de 64 bits
  • As instruções podem ter até 15 bytes de comprimento, e exceder isso gera uma exceção
  • O prefixo de override de endereço permite referenciar endereços de 32 bits no modo de 64 bits

Propriedades estranhas das flags

  • A instrução INC não atualiza a carry flag, ao contrário da instrução ADD
  • As instruções CMPXCHG8B/CMPXCHG16B modificam apenas a zero flag
  • Instruções de shift e rotate deixam a overflow flag em estado indefinido quando a quantidade de shift é maior que 1

Mais surpresas com instruções de shift

  • shr ax, 10h faz um shift de 16 bits no registrador ax, zerando-o
  • shr eax, 20h faz um shift de 32 bits no registrador eax, mas o valor não muda
  • A quantidade de shift é mascarada com 1FH

Segment override

  • Segmentos ainda são usados em código de 32 e 64 bits, principalmente para thread-local storage
  • No Windows, os registradores FS ou GS são usados para referenciar o TEB (Thread Execution Block)
  • Em processos de 32 bits usa-se FS, e em processos de 64 bits usa-se GS
  • No modo de 64 bits, o valor do registrador de segmento não é importante

Segment override: mais curiosidades

  • No modo de 32 bits, o valor real do registrador de segmento referencia o descritor de segmento
  • No modo de 64 bits, a base é controlada por MSR
  • No WinDbg, não é possível ler diretamente o valor de segmento de processos de 64 bits

Conclusão

  • Este texto apresenta uma lista aleatória de curiosidades sobre x86
  • Escrever um emulador ajuda a entender profundamente como a CPU funciona
  • É possível encontrar ótimos recursos no site do Agner Fog

Resumo do GN⁺

  • Explica várias curiosidades e coisas estranhas aprendidas ao escrever emuladores x86 e amd64
  • Escrever um emulador ajuda a entender profundamente como a CPU funciona
  • Aborda várias curiosidades, como as diferentes formas de codificar a instrução int 3, o prefixo REX e segment override
  • É possível encontrar mais recursos no site do Agner Fog

1 comentários

 
GN⁺ 2024-07-11
Comentários do Hacker News
  • O Intel SDM afirma explicitamente que, nas instruções BSF/BSR, o valor de destino fica indefinido quando a entrada é 0. A AMD documenta que, nesse caso, o destino não é modificado
    • A glibc usa o fato não oficial de que, na Intel, o destino não é modificado
    • TZCNT/LZCNT são formas de BSF/BSR com o prefixo F3, que é ignorado em processadores antigos. O mesmo código pode se comportar de forma diferente em CPUs diferentes
  • Há muitas reclamações sobre prefixos, mas esse não é o maior problema. Os bits de extensão REX/VEX/EVEX.RXB são ignorados quando não se aplicam
    • O APX permite que o prefixo REX2 codifique registradores r16-r31, mas não xmm16-xmm31
    • O prefixo EVEX tem layouts diferentes dependendo de vários opcodes
    • O uso dos bits de extensão varia conforme o tipo de registrador
  • Opinião de alguém que gosta de programar em assembly. Aprecia a qualidade estética simples e vertical
    • Compartilha a experiência de ter escrito uma mini VM para explicar a pilha a um amigo de JS
    • Menciona que o amigo está ocupado com desenvolvimento web e não tem tempo para estudar a fundo
  • Lembrou errado que a variante do Salsa20 e o código de máquina estavam em cryp.to. O site do Dan Bernstein é cr.yp.to
    • Compartilha a experiência de ter testado várias implementações ao trabalhar com criptografia de dados em uma startup
  • Recomenda Justine Tunney e o emulador dela. A documentação explica bem como a CPU funciona
  • Discorda da opinião de que escrever um emulador de CPU é a melhor forma de entender uma CPU
    • Construí-la no nível de portas lógicas seria um método melhor
  • Discorda da opinião de que assembly x86 causa mais problemas do que RISC
    • x86 é fácil de analisar, mas MIPS é difícil
  • Expressa respeito por desenvolvedores de emuladores de processadores x86
    • Ao desenvolver um emulador de i386, aprendeu muito sobre chamadas de sistema e ELF
  • Compartilha experiência escrevendo um emulador x86
    • Lembra da experiência de ter escrito um emulador de brinquedo que executava o código inicial da BIOS
  • Compartilha a opinião de que gosta do estilo e do layout do blog