sábado, 27 de agosto de 2016

Porque a industria ratificou offset 0x7c00 do segmento zero (in old x86 systems) ?

Why the industry ratified 0x7c00 offset from 0x0000 segment (in 0ld x86 systems)?
[Warning: Exemplos e descrições discutidas, são para antigas máquinas x86 (IBM computers). Muitas coisas aqui, não são mais válidos em comparação às máquinas atuais.]

Realmente, o endereço 0x7c00 não está relacionado aos sistemas 8086, mas de 8088 (16-bits), este seria o motivo dele não estar sendo citado no manual "Intel Architecture x86" (IA32, como propriamente dito) e 0x7c00 é 31,744 em hexadecimal.

Na época que têm surgido o "IBM PC 5150 PC/AT" com Intel 16-bit, usando apenas 16Kib. Ao ligar, a BIOS processava um "Post-On Self-Test" (POST), depois executava o procedimento
(i.e. Lembre-se de quando o PC está iniciando e aparece o background com algumas opções de apertar alguma tecla para entrar na BIOS; e, ou sobe ou desce algumas informações de dados iniciais sendo testados, exemplo:  "Init USB..... OK!". Isto é um POST em ação! Verificações feita pela BIOS, para saber se o sistema operacional está apto para ser iniciado, lembrando que a RAM não é verificada neste processo. Só é testada na cold boot, o antônimo de "warm"; Qual testa todo o hardware e a RAM; bootstrap é iniciado logo em seguida):



Essa interrupção em alguns lugares é referenciada como "system reboot" ou como "Bootstrap Loader Service", pois é usada geralmente pela BIOS para executar o bootstrap routine. Não é exatamente um "Ctrl+Alt+DEL" (warm boot), mas seria algo "parecido". Quando executado, a interrupção da BIOS inicia o POST e previamente o warm boot é inicializado fazendo o bypass das verificações normalmente feitas num cold boot (i.e. verificação de memória).

Que de certa maneira significa fazer a BIOS certificar da existência de algum dispositivo. Caso houver, o primeiro setor de 512B é carregado para o 0x7c00.

Anteriormente, na época do IBM CP/M-86, a BIOS carregava o MBR em 0x200, e não 0x7c00. Em sistemas de arquitetura 8086 os interrupts vector seria em 0x0 até 0x3ff. Então, 86-DOS não poderia usar entre range de endereço 0x200 à 0x3ff, e assim, o 0x400 foi escolhido.

Forma resumida do bootloader layout:


[obs: Em máquinas "modernas", nada impede de ser mudado alterando o IDT]

Em processadores 8086, o valor inicial de seus blocos de 64Kb é obtido multiplicando por 16 (movendo 4-bits à esquerda), deste modo é feito o alinhamento.
Nas primeiras inicializações do computador, é ler (apenas) o setor do dispositivo que foi escolhido para dar o boot (i.e. A princípio, ela lê o setor de disquete e se a ROM-BIOS não conseguir a leitura, lê o setor do disco rígido). Em seguida, a BIOS (de forma vulgar) carrega esse setor em 0x0000:0x7c00 (segment:offset) e posteriormente, aplica um "jmp" (salto) para o mesmo (i.e Caso as duas leituras falharem, a interrupção 18h [ROM-BASIC] é feita a fim de alguma outra opção para "dar boot". Se não haver nenhuma opção a mensagem de erro é mostrada, esperando ou a reinicialização ou a troca do bootable device.

Por consequência de ser 0x7c00, é pra economizar espaço possível para o SO carregar em 32KiB. Para dar o boot, 512kB; Para os segmentos de dados e pilha carregar os aplicativos, 512kB. E por fim, os 1,024Kb (de 32KiB) podem ser usados espontaneamente até houver uma nova reinicialização do SO, já que só poderá ser definido novamente em próximas inicializações. (i.e. Notou que: 32Kib-1,024Kb=31,744Kb?).

- Tá! Mas... como sabe que será exatamente 512kB? Answer: Já ouviu falar da diretiva .ORG (ORiGin)? Grosso modo, uma "diretiva" e não uma "instrução". Ele faz com que o machine code defina uma nova origem para começar a colocar as instruções do programa compilado.
Exemplo: Num ambiente x86-64 temos .ORG 300h = 00000000h + 00000300h. - Logo, ele diz para o assembler o seguinte: "Assembler, meu velho amigo... estou querendo mudar umas coisas nesse endereço (por default: 0000h )". Na sequência, se obtivermos .ORG 300h, o Assembler vai entender que queremos entrar no endereço default + o valor passado para o .ORG (i.g. Como foi colocado acima). Quando usado .ORG $ + 300h, aplica a diretiva do código do endereço atual + 300h (que é o valor definido para a diretiva).

Ah! Pra não deixar de lado, falando sobre o segmento 0x0000... é uma vantagem de não precisar se preocupar em mudar os seletores de segmento para acessar os Interrupt Vectors e as variáveis da BIOS.


[...] sei lá, só pra não perder o costume.


links recomendado:

** Instruction Manual - 8086 Monitor: For use with the CSP 300 CPU Support Boar
http://www.s100computers.com/Hardware%20Manuals/Seattle%20Computer%20Products/SCP%208086%20Monitor.pdf

** BIOS Interrupt Call
https://en.wikipedia.org/wiki/BIOS_interrupt_call#Interrupt_table