Finalidade dos registros ESI e EDI?


Respostas:


77

Existem algumas operações que você pode fazer com DI / SI (ou suas contrapartes estendidas, se você não aprendeu ASM em 1985). Entre estes estão

REP STOSB
REP MOVSB
REP SCASB

Que são, respectivamente, operações para armazenamento, carregamento e digitalização repetidos (= massa). O que você faz é configurar SI e / ou DI para apontar para um ou ambos os operandos, talvez colocar uma contagem em CX e depois deixar escapar. Essas são operações que funcionam em um monte de bytes de uma vez e meio que colocam a CPU em automático. Como você não está codificando explicitamente os loops, eles funcionam com mais eficiência (geralmente) do que um loop codificado manualmente.

Caso você esteja se perguntando: dependendo de como você configurou a operação, o armazenamento repetido pode ser algo simples, como inserir o valor 0 em um grande bloco contíguo de memória; MOVSB ​​é usado, eu acho, para copiar dados de um buffer (bem, qualquer bando de bytes) para outro; e SCASB é usado para procurar um byte que corresponda a algum critério de pesquisa (não tenho certeza se é apenas uma pesquisa de igualdade, ou o que - você pode pesquisar :))

É para isso que servem esses regs.


7
Dica de otimização do passado: rep stosw é muito mais rápido do que rep stosb , então se copiar dois e dois bytes se encaixa com o que você está tentando fazer, use isso em seu código assembly x86 de 16 bits otimizado à mão ...
Alexander

88

SI= Índice de origem
DI= Índice de destino

Como outros indicaram, eles têm usos especiais com as instruções de string. Para programação em modo real, o ESregistrador de segmento deve ser usado com DIe DScom SIcomo em

movsb  es:di, ds:si

SI e DI também podem ser usados ​​como registradores de índice de propósito geral. Por exemplo, o Ccódigo-fonte

srcp [srcidx++] = argv [j];

compila em

8B550C         mov    edx,[ebp+0C]
8B0C9A         mov    ecx,[edx+4*ebx]
894CBDAC       mov    [ebp+4*edi-54],ecx
47             inc    edi

onde ebp+12contém argv, ebxé je editem srcidx. Observe que a terceira instrução usa edimultiplicado por 4 e adiciona o ebpdeslocamento por 0x54 (a localização de srcp); colchetes em torno do endereço indicam indireção.


Embora não me lembre onde o vi, mas isto confirma a maior parte, e este (slide 17) outros:

AX= acumulador
DX= palavra dupla acumulador
CX= contador
BX= registro base

Eles se parecem com registradores de uso geral, mas há uma série de instruções que (inesperadamente?) Usam um deles - mas qual? ​​- implicitamente.


37

Opcodes como MOVSB ​​e MOVSW que copiam dados de forma eficiente da memória apontada pelo ESI para a memória apontada pelo EDI. Portanto,

mov esi, source_address
mov edi, destination_address
mov ecx, byte_count
cld
rep movsb ; fast!

12

Além das operações de string (MOVS / INS / STOS / CMPS / SCASB / W / D / Q etc.) mencionadas nas outras respostas, gostaria de acrescentar que também existem instruções de montagem x86 mais "modernas" que implicitamente usam em menos EDI / RDI:

A instrução SSE2 MASKMOVDQU(e o próximo AVX VMASKMOVDQU) gravam bytes seletivamente de um registro XMM na memória apontada por EDI / RDI.


6

Além dos registros sendo usados ​​para operações em massa, eles são úteis por sua propriedade de serem preservados por meio de uma chamada de função (chamada preservada) na convenção de chamada de 32 bits. O ESI, EDI, EBX, EBP, ESP são preservados por chamada, enquanto EAX, ECX e EDX não são preservados por chamada. Os registros preservados de chamadas são respeitados pela função da biblioteca C e seus valores persistem por meio das chamadas da função da biblioteca C.

Jeff Duntemann em seu livro de linguagem assembly tem um exemplo de código assembly para imprimir os argumentos da linha de comando. O código usa esi e edi para armazenar contadores, pois eles não serão alterados pela função de biblioteca C printf. Para outros registradores como eax, ecx, edx, não há garantia de que eles não sejam usados ​​pelas funções da biblioteca C.

https://www.amazon.com/Assembly-Language-Step-Step-Programming/dp/0470497025

Veja a seção 12.8 Como C vê os argumentos da linha de comando.

Observe que as convenções de chamada de 64 bits são diferentes das convenções de chamada de 32 bits, e não tenho certeza se esses registros são preservados ou não.


Eu nunca ouvi "sagrado" ser usado para descrever o que a maioria das pessoas chama de "volátil" / "não-volátil", ou "salvo pelo chamador" vs. "salvo pelo chamador". Eu gosto de "chamadas preservadas" / "chamadas destruídas", pois isso não significa que elas realmente sejam salvas em qualquer lugar. De qualquer forma, ESI / RSI e EDI / RDI não são preservados por chamada no x86-64 System V ABI.
Peter Cordes

Além disso, você se esqueceu de listar EBP e ESP como preservados de chamada nas convenções de chamada comuns de 32 bits.
Peter Cordes

1
Enfim, esse é um ponto muito bom. No código real, é mais provável que você escolha EDI / ESI por algo baseado em razões de convenção de chamada do que por serem especiais para quaisquer instruções.
Peter Cordes

Eu gosto de chamada preservada. Eu atualizei a resposta com o mesmo. Obrigado pela revisão.
Jay Rajput,
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.