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?

Foi útil?

Solução

Ver Por que o GCC Lea Eiz?:

Aparentemente %eiz é um pseudo-registro que apenas avalia zero o tempo todo (como r0 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.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top