O que é o registro% eiz?
Pergunta
No código assembly a seguir que despejei usando objdump
:
lea 0x0(%esi,%eiz,1),%esi
O que é registrar %eiz
?O que significa o código anterior?
Solução
Aparentemente
%eiz
é um pseudo-registro que apenas avalia zero o tempo todo (comor0
em mips).
...
Acabei encontrando um post da lista de discussão do guru do Binutils, Lance Taylor, que revela a resposta. Às vezes, o GCC insere as instruções NOP no fluxo de código para garantir o alinhamento adequado e coisas assim. A instrução NOP pega um byte, então você pensaria que poderia adicionar o máximo necessário. Mas, de acordo com Ian Lance Taylor, é mais rápido para o chip executar uma longa instrução do que muitas instruções curtas. Portanto, em vez de inserir sete instruções NOP, eles usam um Bizarro Lea, que usa sete bytes e é semanticamente equivalente a um NOP.
Outras dicas
(Muito tarde para o jogo, mas pareceu uma adição interessante):Não é um registro, é uma peculiaridade da codificação de instruções da Intel.Ao usar um byte ModRM para carregar da memória, são usados 3 bits para o campo de registro armazenar 8 registros possíveis.Mas o local onde o ESP (o ponteiro da pilha) "estaria" é interpretado pelo processador como "um byte SIB segue esta instrução" (ou seja,é um modo de endereçamento estendido, não uma referência ao ESP).Por razões conhecidas apenas pelos autores, o assembler GNU sempre representou este "zero onde de outra forma estaria um registro" como um registro "%eiz".A sintaxe da Intel simplesmente descarta isso.
Andy Ross fornece muito mais do raciocínio subjacente, mas infelizmente está errado ou pelo menos confuso sobre os detalhes técnicos. É verdade que um endereço eficaz de apenas (%esp)
não pode ser codificado apenas com o byte modr/m como em vez de ser decodificado como (%esp)
, é usado para sinalizar que um byte SIB também está incluído. No entanto, o %eiz
O pseudo-registro nem sempre é usado com um byte SIB para representar que um byte SIB foi usado.
O byte sib (escala/índice/base) tem três peças: o índice (um registro como como %eax
ou %ecx
que a escala é aplicada), a escala (uma potência de dois de 1 a 8 em que o registro do índice é multiplicado por) e a base (outro registro que é adicionado ao índice escala). É isso que permite instruções como add %al,(%ebx,%ecx,2)
(Código da máquina: 00 04 4b
- OpCode, Modr/M, SIB (NOTA NO %EIZ REGISTRO, embora o byte SIB tenha sido usado)) (ou na sintaxe da Intel, "Adicionar byte ptr [ecx*2+eBX], AL").
No entanto, %esp
não pode ser usado como registro de índice em um byte SIB. Em vez de permitir essa opção, a Intel adiciona uma opção para usar o registro base como está sem escala ou indexação. Portanto, para desambiguar entre o caso de add %al,(%ecx)
(Código da máquina: 00 01
- Opcode, modr/m) e add %al,(%ecx)
(Código da máquina: 00 04 21
- OpCode, Modr/M, Sib), a sintaxe alternativa add %al,(%ecx,%eiz,1)
Em vez disso, é usado (ou para a sintaxe da Intel: add BYTE PTR [ecx+eiz*1],al
).
E como explicado no artigo vinculado por Sinan, esta instrução específica (lea 0x0(%esi,%eiz,1),%esi
) é apenas usado como um NOP de vários bytes (equivalente a esi = &*esi
) para que apenas uma instrução do tipo NOP deve ser executada em vez de várias instruções NOP.