Por que a primeira instrução da BIOS está localizada em 0xFFFFFFF0 (“topo” da RAM)?

49

Eu sei que o BIOS carrega sua primeira instrução de 0xFFFFFFF0, mas por que esse endereço específico? Eu tenho um monte de perguntas e espero que você possa me ajudar com algumas delas, pelo menos.

Minhas perguntas:

  • Por que a primeira instrução de BIOS está localizada no "topo" de uma RAM de 4 GB?
  • O que aconteceria se meu computador tivesse apenas 1 GB de RAM?
  • E quanto aos sistemas com mais de 4 GB de RAM (por exemplo, 8 GB, 16 GB, etc.)?
  • Por que a pilha foi inicializada com algum valor (nesse caso, um valor localizado em 0xFFFFFFF0)?

Eu li sobre isso esta tarde e ainda não entendi.

    
por Fernando Paladini 18.10.2015 / 23:58

7 respostas

52

0xFFFFFFF0 é onde uma CPU compatível com x86 inicia a execução de instruções quando está ligada. Esse é um aspecto hardwired, imutável (sem hardware extra) da CPU e diferentes tipos de CPUs se comportam de maneira diferente.

Why the first BIOS instruction is located at the "top" of a 4 GB RAM?

Ele está localizado no "topo" de 4 GB espaço de endereço - e na inicialização do BIOS ou UEFI A ROM está configurada para responder a leituras desses endereços.

Minha teoria sobre por que isso é:

Quase tudo na programação funciona melhor com endereços contíguos. O projetista da CPU não sabe o que um construtor de sistemas desejará fazer com a CPU, portanto, é uma má idéia para a CPU exigir que endereços cheios no meio do espaço sejam necessários para várias finalidades. É melhor manter isso "fora do caminho" na parte superior ou inferior do espaço de endereço. É claro, tenha em mente que essa decisão foi tomada quando o 8086 era novo, e não tinha uma MMU .

No 8086, vetores de interrupção existiam no local de memória 0 e acima. Os vetores de interrupção precisam estar em endereços conhecidos e eram desejados em RAM para flexibilidade - ainda que não fosse possível para o designer da CPU saber quanta RAM estaria em um sistema. Então, começar de 0 e trabalhar fazia sentido (porque nenhum sistema em 1978 quando o 8086 foi inventado teria 4 Gbytes de RAM - então esperar que a RAM estivesse em 0xFFFFFF0 não era uma boa idéia), e então ROM teria que ser no limite superior.

É claro que, começando pelo menos o 80286, os vetores de interrupção podem ser movidos para um local diferente diferente de 0, mas os processadores modernos x86 de 64 bits ainda são inicializados no modo 8086, então tudo ainda funciona da maneira antiga para compatibilidade (Por mais ridículo que pareça em 2015 ainda precisar da sua CPU x86 para poder rodar o DOS).

Portanto, como os vetores de interrupção começam de 0 e funcionam para cima, a ROM teria que começar de cima para baixo.

What would happen if my computer has only 1 GB of RAM?

Uma CPU de 32 bits possui 4.294.967.296 endereços, numerados de 0 (0x00000000) a 4294967295 (0xFFFFFFFF). ROM pode viver em alguns endereços e RAM pode viver em outros. Com o MMU da CPU, isso pode até mesmo ser ligado imediatamente. A RAM não precisa viver em todos os endereços.

Com apenas 1 GB de RAM, alguns endereços não terão resposta quando forem lidos ou gravados. Isso pode fazer com que dados inválidos sejam lidos quando esses endereços forem acessados ou um bloqueio do sistema.

What about systems with more than 4 GB of RAM (e.g: 8 GB, 16 GB, etc.)?

Mantendo a simplicidade: as CPUs de 64 bits têm mais endereços (o que os torna 64 bits, por exemplo, 0x0000000000000000 a 0xFFFFFFFFFFFFFFFF), por exemplo, para que a RAM extra "se encaixe". Assumindo que a CPU esteja no modo longo . Até lá, a RAM está lá, só não endereçável.

Why is stack initialized with some value (in this case, a value located at 0xFFFFFFF0)?

Não consigo encontrar nada imediatamente no que o x86 atribui o ponteiro da pilha ao ligar, mas eventualmente teria que ser reatribuído por uma rotina de inicialização, uma vez que a rotina descobre quanta RAM está no sistema. (@Eric Towers nos comentários abaixo informa que está definido para zero na inicialização.)

    
por 19.10.2015 / 02:26
24

Não está localizado no topo da RAM; Ele está localizado na ROM, cujo endereço está no topo do espaço de endereço de memória, junto com qualquer memória nas placas de expansão, como os controladores Ethernet. Ele está lá para não entrar em conflito com a RAM, pelo menos até que você tenha 4 GB instalados. Sistemas com 4 GB ou mais de RAM podem fazer duas coisas para resolver o conflito. Placas-mãe baratas simplesmente ignoram as partes da RAM que entram em conflito com a localização da ROM. Os decentes remapearam que a RAM parece ter um endereço acima da marca de 4 GB.

Não tenho certeza do que você está perguntando sobre a pilha. Certamente não é inicializado para estar na ROM. Quando a CPU é redefinida, ela está inicialmente em "modo real", onde atua exatamente como o 8086 original e usa endereçamento segmentado de 16 bits, permitindo que apenas acesse 1 MB de memória. O código do BIOS está localizado no topo desse 1 MB. O BIOS escolhe algum lugar na RAM para configurar a pilha e carrega e executa o primeiro setor da primeira unidade inicializável. Cabe ao sistema operacional alternar para o modo de 32 ou 64 bits quando ele assumir e configurar suas próprias pilhas (uma por tarefa / thread).

    
por 19.10.2015 / 01:19
11

Primeiro, isso não tem nada a ver com RAM, na verdade. Estamos falando de espaço de endereçamento aqui - mesmo se você tiver apenas 16 MiB de memória, você ainda tem 32 bits completos de espaço de endereço em uma CPU de 32 bits.

Isso já responde à sua primeira pergunta, na verdade - no momento em que isso foi projetado, os PCs do mundo real não tinham nem perto dos 4 GiB de memória; eles estavam mais na faixa de 1-16 MiB de memória. O espaço de endereço era, para todos os efeitos, livre.

Agora, por que exatamente 0xFFFFFF0? A CPU não sabe quanto da BIOS existe. Alguns BIOSes podem levar apenas alguns kilobytes, enquanto outros podem ter megabytes de memória - e eu nem estou entrando nas várias RAMs opcionais. A CPU deve ser conectada a algum endereço para iniciar - não há como configurar a CPU. Mas isso é apenas um mapeamento do espaço de endereçamento - o endereço é mapeado diretamente no chip ROM da BIOS (sim, isso significa que você não tem acesso a todos os 4 GiB de RAM neste ponto se você tiver tantos - mas isso não é nada de especial, muitos dispositivos exigem seu próprio intervalo no espaço de endereço). Em uma CPU de 32 bits, esse endereço fornece 16 bytes completos para fazer a inicialização básica - o que é suficiente para configurar seus segmentos e, se necessário, o modo de endereço (lembre-se, x86 é inicializado no modo real de 16 bits) não é plana) e pule para o real boot "procedure". Neste ponto, você não usa RAM - é tudo apenas mapeado ROM. Na verdade, a RAM não está pronta para ser usada neste momento - essa é uma das tarefas do BIOS POST! Agora, você pode estar pensando: como um modo real de 16 bits acessa o endereço 0xFFFFFFF0? Claro, há segmentos, então você tem um espaço de endereçamento de 20 bits, mas isso ainda não é suficiente. Bem, há um truque para isso - os 12 bits altos do endereço são definidos até que você execute seu primeiro salto em distância, dando acesso ao alto espaço de endereço (enquanto rejeita o acesso a qualquer coisa menor que 0xFFF00000 - até você executar um salto em distância) .

Tudo isso é basicamente escondido dos programadores (para não mencionar usuários) nos sistemas operacionais modernos. Você normalmente não tem acesso a nada de tão baixo nível - algumas coisas já estão além do salvamento (você não pode alternar os modos de CPU a sério), alguns são tratados exclusivamente pelo kernel do SO.

Portanto, uma visão melhor vem da codificação old-school no MS DOS. Outro exemplo típico de memória do dispositivo sendo diretamente mapeada para o espaço de endereço é o acesso direto à memória de vídeo. Por exemplo, se você quisesse escrever texto rapidamente no display, escrevia diretamente para o endereço B800:0000 (mais offset - no modo de texto 80x25, isso significava (y * 80 + x) * 2 se minha memória me serve corretamente - dois bytes por caractere, linha por linha). Se você quisesse desenhar pixel por pixel, você usou um modo gráfico e o endereço inicial de A000:0000 (normalmente, 320x200 a 8 bits por pixel). Fazer algo de alto desempenho geralmente significa mergulhar nos manuais dos dispositivos, para descobrir como acessá-los diretamente.

Isso sobrevive até hoje - é apenas escondido. No Windows, você pode ver os endereços de memória mapeados para dispositivos no Gerenciador de dispositivos - basta abrir as propriedades de algo como sua placa de rede, vá para a guia Recursos - todos os itens de Intervalo de memória são mapeamentos da memória do dispositivo para seu espaço de endereço principal. E em 32 bits, você verá que a maioria desses dispositivos é mapeada acima da marca de 2 GiB (mais tarde, de 3 GiB) - novamente, para minimizar conflitos com memória utilizável pelo usuário, embora isso não seja realmente um problema com a memória virtual ( os aplicativos não chegam perto do espaço de endereço real, hardware - eles têm seu próprio bloco de memória virtualizado, que pode ser mapeado para RAM, ROM, dispositivos ou o arquivo de paginação, por exemplo). / p>

Quanto à pilha, bem, deve ajudar a entender que, por padrão, a pilha cresce a partir do topo. Portanto, se você fizer um push , o novo ponteiro da pilha estará em 0xFFFFFEC - em outras palavras, você não está tentando gravar no endereço de inicialização do BIOS :) O que significa que as rotinas de inicialização do BIOS podem usar o empilhe com segurança, antes de remapear em algum lugar mais útil. Na programação old-school, antes que a paginação se tornasse o padrão de fato, a pilha geralmente começava no final da RAM, e o "estouro de pilha" acontecia quando você começou a sobrescrever a memória do seu aplicativo. A proteção da memória mudou muito isso, mas, em geral, mantém compatibilidade com versões anteriores - note como até mesmo a mais moderna CPU x86-64 ainda pode inicializar o MS DOS 5 - ou como o Windows ainda pode executar muitos aplicativos DOS que não têm idéia sobre paginação.

    
por 19.10.2015 / 15:19
5

Além dos outros pontos mencionados, pode ser útil entender o que é um endereço . Enquanto as arquiteturas mais novas complicam as coisas, historicamente uma máquina faria em cada ciclo de memória o endereço desejado em 20 a 32 fios (dependendo da arquitetura, com alguns truques especiais para observar se precisava de um par ou quarteto de bytes simultaneamente); várias partes do sistema de memória examinariam o estado desses fios e se ativariam quando vissem certas combinações de valores altos e baixos.

Se uma máquina com 32 fios de endereço só precisasse usar 1MB de RAM e 64KB de ROM [bastante plausível para alguns controladores embutidos] ele pode ativar a RAM para todos os endereços onde o fio de endereço superior era baixo e a ROM para todos os endereços onde estava alto. Os 20 fios inferiores de endereço então ser amarrado à RAM para selecionar um dos 1.048.576 bytes e o fundo 16 também seria conectado à ROM, para selecionar um dos 65.536 bytes. Os restantes 11 fios de endereço simplesmente não seriam conectados a qualquer coisa.

Em tal máquina, os acessos aos endereços 0x00100000-0x001FFFFF seriam equivalente a acessos a endereços de RAM 0x00000000-0x000FFFFF. Da mesma forma com endereços 0x000200000-0x0002FFFFF ou 0x7FF00000-0x7FFFFFFFF. Endereços acima 0x80000000 todos ler ROM, com um padrão de 64 K repetindo em todo o espaço.

Embora o processador tenha um espaço de endereço de 4.294.967.296 bytes, há Não é necessário que o hardware reconheça muitos endereços distintos. Colocando o vetor de redefinição perto do topo do espaço de endereço é um projeto que irá funcionam bem, independentemente de quanto ou quão pouco RAM e ROM o sistema tem e evita a necessidade de decodificar totalmente o espaço de endereço.

    
por 20.10.2015 / 02:21
2

Minha teoria é porque estamos usando lógica negativa, a digital (1) não tem tensão nenhuma (O volts) Nós só temos que colocar tensão nos últimos 4 bits na inicialização, então o contador de programa (ou ponteiro de instrução) lacera em 1111 1111 1111 1111 1111 1111 1111 0000. Nós não temos que endereçar os 28 bits superiores, já que a maioria das (antigas) CPUs foram 16 bits e os nibbles inferiores podem ser endereçados por um único chip de endereço nos velhos tempos. Agora, como temos 64 bits com compatibilidade para 32 bits e 32 bits para 16 bits, o couild de hardware foi aprimorado, mas o método permanece. Também os bioses nem sempre são 64 bits ou 32 bits programados. Minha opinião é também, já que as lembranças não são sempre as mesmas, a bios deve estar localizada no mesmo primeiro segmento. A maneira como vemos a biografia abordada não é o endereço real o tempo todo. Apenas um ensinou de mim ...

    
por 22.10.2015 / 09:25
1

no RESET uma cpu compatível com 8088/8086 executa as instruções em 0FFFF0, que é 16 bytes abaixo do limite de 1 megabyte. normalmente a ROM neste local (em implementações de PC) seria o BIOS, então no final da ROM do BIOS, há um salto para o início do BIOS rom.

mostrado aqui: inicie a assinatura vector e 'date', IBM 5150 PC 8KB eprom dump bios date: 10/19/1981

00001FEE  FF                db 0xff
00001FEF  FF                db 0xff
00001FF0  EA5BE000F0        jmp word 0xf000:0xe05b
00001FF5  3130              xor [bx+si],si
00001FF7  2F                das
00001FF8  3139              xor [bx+di],di

note que o endereçamento é de um 8KB $ 2000 rom, que coloca o endereço inicial (o JMP absoluto longe, para qualquer outro local, neste caso dentro do próprio 8KB rom, embora não seja o endereço mais baixo possível dentro de rom) $ FFFF: $ 0 segmentado ou $ FFFF0 linear.

quanto à compatibilidade: se algum processador 'futuro' ou atual 'espera' ter muito mais F's na frente do endereço, isso não importa. Para compatibilidade de CPUs mais recentes em sistemas mais antigos, as linhas de endereço adicionais permanecem desconectadas e, portanto, os dados no barramento de dados são exatamente os mesmos. contanto que os bits menos significativos permaneçam FFFF0.

(em um sistema com apenas 1 mb de ram e a rom posicionada no final desse RAM, e nada mais, será feliz "pensar" que ele está falando com o endereço mais alto e ainda obter os mesmos dados, porque essas implementações nunca ouvi falar de linhas de endereço superiores a A19)

note que o mundo não é apenas 'pcs' ... o ibm pc foi um 'acidente', esses processadores nunca foram projetados especificamente para 'pcs' e entram em muitas outras coisas além de apenas como satélites, sistemas de armas, etc). O modo protegido de 32 e 64 bits geralmente não é desejado. (O modo virtual 8086 é muito mais interessante como motivo para escolher uma versão mais recente (386+), por exemplo). Portanto, há muito mais para 'compatibilidade com versões anteriores' do que apenas 'será executado dos'.

    
por 03.05.2017 / 03:25
0

A placa-mãe garante que a instrução no vetor de reinicialização seja um salto para o local de memória mapeado para o ponto de entrada do BIOS. Este salto desativa implicitamente o endereço base oculto presente na energização. Todos esses locais de memória têm o conteúdo correto necessário para a CPU, graças ao mapa de memória mantido pelo chipset. Eles estão todos mapeados para a memória flash que contém o BIOS, já que neste momento os módulos de RAM têm uma porcaria aleatória.

    
por 02.06.2018 / 17:54