Pergunta

%AX = (%AH + %AL)

Então, por que não %EAX = (%SOME_REGISTER + %AX) por algum %SOME_REGISTER registo?

Foi útil?

Solução

Apenas para alguns esclarecimentos. Nos dias de microprocessadores início da década de 1970, CPUs teve apenas um pequeno número de registos e um conjunto de instruções muito limitado. Normalmente, a unidade aritmética só poderia operar em um cadastro único CPU, muitas vezes referido como o "acumulador". O acumulador no 8 bits 8080 e Z80 processadores foi chamado de "A". Foram 6 os outros registos de uso geral 8 bits: B, C, D, E, H e L. Estes seis registos poderiam ser emparelhados para formar 3 16 registos de bits: BC, DE e HL. Internamente, o acumulador foi combinado com as bandeiras registar-se para formar o registo AF 16 bits.

Quando a Intel desenvolveu a família de 16 bits 8086 que queria ser capaz de código de porta 8080, assim que mantiveram a mesma estrutura básica registo:

8080/Z80  8086
A         AX
BC        BX
DE        CX
HL        DX
IX        SI    
IY        DI

Por causa da necessidade de código de porta de 8 bits que precisavam de ser capaz de se referir aos 8 partes bits individuais de AX, BX, CX e DX. Estes são chamados AL, AH para as baixas e altas bytes de AX e assim por diante para BL / BH, CL / CH & DL / DH. IX e IY na Z80 só foram sempre usados ??como registros de ponteiro de 16 bits, então não havia necessidade de acesso as duas metades do SI e DI.

Quando o 80386 foi lançado em meados de 1980 eles criaram "estendida" versões de todos os registros. Assim, tornou-se AX EAX, BX se tornou EBX etc. Não houve necessidade de acesso ao topo de 16 bits desses novos registros prolongados, para que eles não criar um registo EAXH pseudo.

AMD aplicado o mesmo truque quando eles produziram os primeiros processadores de 64 bits. A versão do registo AX 64 bits é chamada RAX. Então, agora você tem algo que se parece com isso:

|63..32|31..16|15-8|7-0|
               |AH.|AL.|
               |AX.....|
       |EAX............|
|RAX...................|

Outras dicas

Há um monte de respostas postadas aqui, mas nenhum realmente responder à pergunta dada: Por que não há um registro que codifica directamente as altas de 16 bits de EAX, ou os altos 32 bits de RAX? A resposta resume-se às limitações da instrução x86 codificação em si.

16-Bit History Lesson

Quando a Intel projetou o 8086, eles usaram um esquema de codificação de comprimento variável para muitas das instruções. Isto significava que certas instruções extremamente comuns, como POP AX, pode ser representado como um único byte (58), enquanto instruções raros (mas ainda potencialmente úteis) como MOV CX, [BX*4+BP+1023] ainda pode ser representado, mesmo que levou vários bytes para armazená-los (em neste exemplo, 8B 8C FF 03).

Isto pode parecer uma solução razoável, mas quando o projetou, que preencheu a maior parte do espaço disponível . Assim, por exemplo, havia oito instruções POP para os oito registos individuais (AX, CX, DX, BX, SP, BP, SI, DI), e eles preencheram opcodes 58 até 5F, e opcode 60 era algo totalmente diferente ( PUSHA), como foi opcode 57 (PUSH DI). Não há espaço de sobra para qualquer coisa antes ou depois desses. Mesmo empurrando e estalando os registradores de segmento - que é conceitualmente quase idêntico ao empurrar e estalando os registradores de uso geral - tinha de ser codificado em um local diferente (baixo em torno de 06 / 0E / 16 / 1E) apenas porque não havia espaço ao lado o resto do impulso instruções / pop.

Do mesmo modo, o "r mod / m" byte usado para uma instrução complexa como MOV CX, [BX*4+BP+1023] tem apenas três bits para codificar o registo, o que significa que só pode representar oito registos totais. Isso é bom se você só tem oito registros, mas apresenta um problema real, se você quiser ter mais.

(Há um excelente mapa de todas essas alocações de bytes na arquitetura x86 aqui: http://i.imgur.com/xfeWv .png . Observe como não há espaço deixado no mapa principal, com algumas instruções sobreposição de bytes, e até mesmo quanto do mapa secundário "0F" é usado agora, graças às instruções MMX e SSE).

na direcção 32 e 64 bits

Assim, para até mesmo permitir que o design de CPU para ser estendido a partir de 16 bits para 32 bits, eles já tinham um problema de design, e eles resolveram que, com prefixo bytes : Ao adicionar um especial "66" byte na frente de todas as instruções de 16 bits padrão, a CPU sabe que você quer a mesma instrução, mas a versão de 32-bit (EAX) em vez da versão de 16 bits (AX). O resto do projeto continua o mesmo:. Ainda havia apenas oito Total de registros de uso geral na arquitetura geral da CPU

hackery Semelhante tinha que ser feito para estender a arquitetura de 64-bits (RAX e amigos); lá, o problema foi resolvido através da adição de mais um conjunto de códigos de prefixo (REX, 40-4F) que significava "64-bit" (e eficazmente adicionados mais dois bits para o campo de "mod r / m"), e também descartando estranho instruções antigos ninguém nunca utilizado e reutilizar seus códigos de byte para o material mais recente.

Um aparte sobre os registos de 8 bits

Uma das questões mais importantes a fazer, então, é como as coisas Parreira como AH e AL já trabalhou em primeiro lugar, se só há realmente quarto no projeto para oito registros. A primeira parte da resposta é que não há tal coisa como "PUSH AL" - algumas instruções simplesmente não pode funcionar nos registros de tamanho de byte em tudo! Os únicos que podem são algumas excentricidades especiais (como AAD e XLAT) e versões especiais das instruções de "mod r / H": Por ter um pouco muito específico virado no "mod m r /" byte, aqueles "instruções prolongados "poderia ser virado para operar nos registros em vez de os 16 bits de 8 bits. Acontece que há exatamente oito registradores de 8 bits, também: AL, CL, DL, BL, AH, CH, DH, e BH (por esta ordem), e que se alinha muito bem com os oito ranhuras de registo disponíveis no "r m mod /" byte.

Intel observou na época que o projeto 8086 era suposto ser "fonte compatível" com o 8080/8085: Houve uma instrução equivalente em 8086 para cada um dos 8080/8085 instruções, mas não usar o mesmos códigos de byte (eles não estão nem perto), e você teria que recompilar (remontagem) o seu programa para obtê-lo a utilizar os novos códigos de byte. Mas "fonte compatível" foi um caminho a seguir para software de idade, e permitiu que o 8085 de um indivíduo, B, C "BC", etc. e combinação e "de" registros de ainda trabalhar no novo processador, mesmo se eles estavam agora chamado de "AL" e "BL" e "BX" e "DX" (ou o que o mapeamento foi).

Assim que é realmente a resposta real: Não é que a Intel ou AMD intencionalmente "deixado de fora" um registo de 16 bits alta para EAX, ou um registro de alta de 32 bits para RAX: É que os registos elevados de 8 bits são um estranho sobra anomalia histórica, e replicar seu projeto em tamanhos de bits mais altas seria muito difícil, dada a exigência de que a arquitetura seja compatível com versões anteriores.

A Desempenho Consideração

Há uma outra consideração a respeito de porque os "altos registos" não foram adicionados desde então, assim: arquiteturas moderno processador dentro, por motivos de desempenho, os registros de tamanho variável realmente não sobreposição de verdade: AH e AL não fazem parte do AX, e AX não é uma parte do EAX e EAX não é uma parte de RAX: Eles são todos os registos separados sob o capô, eo processador define um sinalizador invalidação sobre os outros quando você manipular um deles para que ele saiba que terá de copiar os dados quando você lê a partir dos outros.

(Por exemplo: Se você definir AL = 5, o processador não atualiza AX Mas se você, em seguida, ler a partir AX, o processador rapidamente cópias que 5 de AL em bits de fundo do machado..)

Ao manter os registos separados, a CPU pode fazer todo tipo de coisas inteligentes como registo invisível renomeando para fazer sua corrida código mais rápido, mas isso significa que o seu código é executado mais lento Se você não usar o velho padrão de tratar os pequenos registros como pedaços de registros maiores, porque o processador terá que parar e atualizá-los. Para manter toda esta contabilidade interna de ficar fora de mão, os designers da CPU sabiamente optou por adicionar registos separados nos processadores mais recentes, em vez de adicionar registros mais sobrepostas.

(E sim, isso significa que ele realmente é mais rápido em processadores modernos para explicitamente "MOVZX EAX, value" do que fazê-lo da maneira antiga, sloppier de "MOV AX, value / use EAX".)

Conclusão

Com tudo o que disse, poderia Intel e AMD adicionar mais "sobreposição" registros se eles realmente realmente queria? Certo. Existem maneiras de verme-los em se havia demanda suficiente. Mas, dada a bagagem significativa histórico, as atuais limitações de arquitetura, as limitações de desempenho notáveis, eo fato de que a maioria de código nos dias de hoje é gerada por compiladores otimizados para não-sobreposição de registros, é altamente improvável que eles vão adicionar essas coisas em breve.

Nos velhos tempos, de 8 bits, havia a um registo.

Nos dias 16 bits, houve o registro AX 16 bit, que foi dividido em duas partes 8 bits, AH e AL, para aqueles momentos em que você ainda queria trabalhar com 8 bit valores.

Nos dias 32 bits, o registro EAX 32 bit foi introduzida, mas o AX, registradores AH e AL foram todos mantidos. Os designers não sentir que é necessário introduzir um novo registo de 16 bits que abordou os bits 16 a 31 de EAX.

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