A Aldeia Numaboa ancestral ainda está disponível para visitação. É a versão mais antiga da Aldeia que eu não quis simplesmente descartar depois de mais de 10 milhões de pageviews. Como diz a Sirley, nossa cozinheira e filósofa de plantão: "Misericórdia, ai que dó!"

Se você tiver curiosidade, o endereço é numaboa.net.br.

Leia mais...

Oficina

6. O setor de boot

Sab

26

Mai

2007


14:48

(16 votos, média 4.75 de 5) 


Nível avançado MÓDULO 6 do SO Numaboa

Todo sistema operacional precisa ser acionado quando o computador é ligado ou reiniciado (ressetado). O hardware da máquina já vem preparado "de fábrica" para procurar informações em determinados lugares - os assim chamados setores de boot.

Antes de iniciar qualquer projeto de SO, sabendo de antemão que o setor de boot será o primeiro que a máquina procura, é preciso ter uma idéia clara do que é um setor de boot. Neste tutorial você encontra uma verdadeira radiografia do setor de boot de um disquete formatado pelo DOS. Parto do pressuposto que você tenha conhecimentos suficientes de Assembly para acompanhar o texto.

Se os seus conhecimentos de Assembly forem insuficientes, ainda assim vale a pena dar uma lida no texto. Imagine que o setor de boot seja uma sequência de bits localizados logo no início do disquete. Esta sequência de bits é dividida em algumas partes e cada uma delas contém determinados tipos de dados e informações.

Onde está o setor de boot

O setor de boot de um disquete está localizado no cilindro 0, cabeça 0, setor 1. Este setor é criado por um programa de formatação de disquetes, como o FORMAT do DOS. O setor de boot de uma partição FAT de um disco rígido tem um layout e função semelhantes. Uma partição FAT "bootável" se parece com um disquetão durante os estágios iniciais do processo de boot do sistema.

O processo de boot

Quando o computador é ligado ou reiniciado, a BIOS executa um teste conhecido como POST (Power On Self Test). O POST verifica toda a memória, testa todas as placas e o hardware é rastreado. É através do POST que o computador é informado do número e dos tipos de placas, de drives de disquete, de HDs, de portas seriais, paralelas e USBs, do monitor, do mouse, do teclado, etc.

Após o sistema completar o POST, a interrupção 19 (INT 19) é chamada. Normalmente a INT 19 tenta ler o setor de boot do primeiro drive de disquete. Se for encontrado um setor de boot no disquete, este é lido e transferido para a memória no endereço 0000:7C00 e a INT 19 salta para o endereço de memória 0000:7C00. Entretanto, se não for encontrado um setor de boot no primeiro drive, a INT 19 tenta fazer a leitura do MBR (Master Boot Record) do primeiro disco rígido. Se um MBR for encontrado, ele é lido e transferido para a localização de memória 0000:7C00 e a INT 19 salta para o endereço de memória 0000:7C00. O pequeno programa no MBR tentará localizar uma partição ativa ("bootável") na sua tabela de partições. Se uma partição "bootável" for encontrada, o setor de boot desta partição é lida e transferida para o endereço de memória 0000:7C00 e o programa do MBR salta para o endereço de memória 0000:7C00. Cada sistema operacional possui um formato de setor de boot próprio. O pequeno programa no setor de boot precisa localizar a porção inicial do programa carregador (loader) do kernel do sistema operacional (ou, talvez, o próprio kernel ou um "programa gerenciador de boot") e transferi-lo para a memória.

A INT 19 também é chamada quando as teclas Ctrl+Alt+Del são pressionadas simultaneamente. Na maioria dos sistemas, Ctrl+Alt+Del disparam uma versão reduzida do POST, que é executada antes da chamada à INT 19.

Dissecando o setor de boot

Para começar, observe logo abaixo o setor de boot de um disquete mostrado em hexadecimal e em ASCII. Os deslocamentos destacados em vermelho mostram o início das principais áreas:

  • O BPB (BIOS Parameter Block) começa no deslocamento (offset) 0.
  • O programa do setor de boot começa no deslocamento 3E.
  • As mensagens fornecidas pelo programa começam no deslocamento 19E.
  • O nomes dos arquivos ocultos do DOS começam no deslocamento 1E6.
  • A assinatura do setor de boot está no deslocamento 1FE.
OFFSET 0 1 2 3  4 5 6 7  8 9 A B  C D E F  *0123456789ABCDEF*
000000 eb3c904d 53444f53 352e3000 02010100 *...MSDOS5.0.....*
000010 02e00040 0bf00900 12000200 00000000 *...@............*
000020 00000000 0000295a 5418264e 4f204e41 *......)ZT..NO NA*
000030 4d452020 20204641 54313220 2020fa33 *ME    FAT12   .3*
000040 c08ed0bc 007c1607 bb780036 c5371e56 *.....|...x.6.7.V*
000050 1653bf3e 7cb90b00 fcf3a406 1fc645fe *.S..|.........E.*
000060 0f8b0e18 7c884df9 894702c7 073e7cfb *....|.M..G....|.*
000070 cd137279 33c03906 137c7408 8b0e137c *..ry3.9..|t....|*
000080 890e207c a0107cf7 26167c03 061c7c13 *.. |..|...|...|.*
000090 161e7c03 060e7c83 d200a350 7c891652 *..|...|....P|..R*
0000a0 7ca3497c 89164b7c b82000f7 26117c8b *|.I|..K|. ....|.*
0000b0 1e0b7c03 c348f7f3 0106497c 83164b7c *..|..H....I|..K|*
0000c0 00bb0005 8b16527c a1507ce8 9200721d *......R|.P|...r.*
0000d0 b001e8ac 0072168b fbb90b00 bee67df3 *.....r........}.*
0000e0 a6750a8d 7f20b90b 00f3a674 18be9e7d *.u... .....t...}*
0000f0 e85f0033 c0cd165e 1f8f048f 4402cd19 *._.3...^....D...*
000100 585858eb e88b471a 48488a1e 0d7c32ff *XXX...G.HH...|2.*
000110 f7e30306 497c1316 4b7cbb00 07b90300 *....I|..K|......*
000120 505251e8 3a0072d8 b001e854 00595a58 *PRQ.:.r....T.YZX*
000130 72bb0501 0083d200 031e0b7c e2e28a2e *r..........|....*
000140 157c8a16 247c8b1e 497ca14b 7cea0000 *.|..$|..I|.K|...*
000150 7000ac0a c07429b4 0ebb0700 cd10ebf2 *p....t).........*
000160 3b16187c 7319f736 187cfec2 88164f7c *;..|s..6.|....O|*
000170 33d2f736 1a7c8816 257ca34d 7cf8c3f9 *3..6.|..%|.M|...*
000180 c3b4028b 164d7cb1 06d2e60a 364f7c8b *.....M|.....6O|.*
000190 ca86e98a 16247c8a 36257ccd 13c30d0a *.....$|.6%|.....*
0001a0 4e6f6e2d 53797374 656d2064 69736b20 *Non-System disk *
0001b0 6f722064 69736b20 6572726f 720d0a52 *or disk error..R*
0001c0 65706c61 63652061 6e642070 72657373 *eplace and press*
0001d0 20616e79 206b6579 20776865 6e207265 * any key when re*
0001e0 6164790d 0a00494f 20202020 20205359 *ady...IO      SY*
0001f0 534d5344 4f532020 20535953 000055aa *SMSDOS   SYS..U.*

O BPB (BIOS Parameter Block)

Os primeiros 62 bytes de um setor de boot são conhecidos como BPB (BIOS Parameter Block - Bloco de Parâmetros da BIOS). Lembre-se de que o conteúdo do setor de boot é transferido para o endereço de memória 0000:7C00. Analisando o setor de boot mostrado anteriormente, o BPB mostra o seguinte:

	7C00	eb3c		db instrução JMP
	7C02	90		db instrução NOP
	7C03	'MSDOS5.0'	db OEMname
	7C0B	0200		dw bytesPerSector; 00 02 -> 02 00
	7C0D	01		db sectPerCluster
	7C0E	0001		dw reservedSectors; 01 00 -> 00 01
	7C10	02		db numFAT
	7C11	00e0		dw numRootDirEntries; e0 00 -> 00 e0
	7C13	0b40		dw numSectors; ignorar numSectorsHuge
	7C15	f0		db mediaType
	7C16	0009		dw numFATsectors
	7C18	0012		dw sectorsPerTrack
	7C1A	0002		dw numHeads
	7C1C	00000000	dd numHiddenSectors
	7C20	00000000	dd numSectorsHuge
	7C24	00		db driveNum
	7C25	00		db reserved
	7C26	29		db signature
	7C27	5a541826	dd volumeID
	7C2B	'NO NAME   '	db volumeLabel
	7C36	'FAT12   '	db fileSysType

A Tabela de Parâmetros do Disquete

Os 11 bytes com início em 0000:7C3E são imediatamente sobrepostos com informações copiadas de outra parte da memória. Esta informação é a Tabela de Parâmetros do Disquete. Estes dados são apontados pela INT 1E e são os seguintes:

	7C3E = Taxa de passo (step rate) e
		tempo de descarga da cabeça (head unload time).
	7C3F = Tempo de carga da cabeça (head load time) e
		flag de modo do DMA.
	7C40 = Retardo para o motor desligar.
	7C41 = Bytes por setor.
	7C42 = Setores por trilha.
	7C43 = Comprimento da lacuna entre os setores.
	7C44 = Comprimento dos dados.
	7C45 = Comprimento da lacuna entre os setores durante a formatação.
	7C46 = Valor do byte da formatação.
	7C47 = Tempo do ajuste da cabeça (head settling time).
	7C48 = Retardo até que o motor atinja a velocidade normal.

Os 11 bytes seguintes, com início em 0000:7C49, também são sobrepostos pelos seguintes dados:

	7C49 - 7C4C = endereço do setor do disquete (como LBA)
			da área de dados.
	7C4D - 7C4E = número do cilindro onde deve ser feita a leitura.
	7C4F - 7C4F = número do setor onde dever ser feita a leitura.
	7C50 - 7C53 = endereço do setor do disquete (como LBA) do
			diretório raiz.

O programa do setor de boot desassemblado

A seguir, o código em Assembly do programa do setor de boot. É um tanto extenso, mas vale a pena dar uma olhada. Não se preocupe se não identificar todas as instruções utilizadas. À medida que avançarmos nos tutoriais, elas serão referenciadas.

	INICIO:             INÍCIO DO PROGRAMA DO SETOR DE BOOT

0000:7C3E FA          CLI                 desliga as interrupções
0000:7C3F 33C0        XOR     AX,AX       zera AX
0000:7C41 8ED0        MOV     SS,AX       SS agora é zero
0000:7C43 BC007C      MOV     SP,7C00     SP agora é 7C00
0000:7C46 16          PUSH    SS          põe zero na pilha
0000:7C47 07          POP     ES             e zera ES

                              O vetor da INT 1E etá em 0000:0078.
                              Pega o endereço apontado pelo vetor
                              e o coloca nos registradores DS:SI.

0000:7C48 BB7800      MOV     BX,0078     BX agora é 78
0000:7C4B 36          SS:
0000:7C4C C537        LDS     SI,[BX]     DS:SI agora é [0:78]
0000:7C4E 1E          PUSH    DS          salva DS:SI --
0000:7C4F 56          PUSH    SI             salva end tab param
0000:7C50 16          PUSH    SS          salva SS:BX --
0000:7C51 53          PUSH    BX             salva end da INT 1E

                              Move a tabela de parâmetros do
                              disquete para 0000:7C3E.

0000:7C52 BF3E7C      MOV     DI,7C3E     DI é o endereço de START
0000:7C55 B90B00      MOV     CX,000B     contador é 11
0000:7C58 FC          CLD                 limpa a direção
0000:7C59 F3          REPZ                move a tabela de parâmetros
0000:7C5A A4          MOVSB                  do disquete para 0000:7C3E
0000:7C5B 06          PUSH    ES          também zera
0000:7C5C 1F          POP     DS             DS

                              Altera alguns dados da tabela de
                              parâmetros do disquete.

0000:7C5D C645FE0F    MOV     BYTE PTR [DI-02],0F  muda o tempo de ajuste
                                                   da cabeça em 0000:7C47
0000:7C61 8B0E187C    MOV     CX,[7C18]            setores por trilha
0000:7C65 884DF9      MOV     [DI-07],CL              salva em 0000:7C42

                              Muda INT 1E para que aponte para a tabela de
                              parâmetros do disquete alterada em 0000:7C3E

0000:7C68 894702      MOV     [BX+02],AX           muda segmento da INT 1E
0000:7C6B C7073E7C    MOV     WORD PTR [BX],7C3E   muda deslocamento 
                                                      da INT 1E

                              Chama INT 13 com AX=0000, reset de disco, de
                              modo que a nova tabela de parâmetros do
                              disquete seja usada.

0000:7C6F FB          STI                          liga as interruções
0000:7C70 CD13        INT     13                   faz chamada do reset do
                                                      disquete
0000:7C72 7279        JB      TALK                 salta se houver erro

                              Detemina o endereço inicial do setor do
                              diretório raiz como um LBA.

0000:7C74 33C0        XOR     AX,AX                AX agora é zero
0000:7C76 3906137C    CMP     [7C13],AX            néumero de setores zero?
0000:7C7A 7408        JZ      SMALL_DISK           sim
0000:7C7C 8B0E137C    MOV     CX,[7C13]            número de setores
0000:7C80 890E207C    MOV     [7C20],CX            salva em número gigante


	DISCO_PEQUENO:

0000:7C84 A0107C      MOV     AL,[7C10]            número de tabelas FAT
0000:7C87 F726167C    MUL     WORD PTR [7C16]      número de setores FAT
0000:7C8B 03061C7C    ADD     AX,[7C1C]            nro de setores escondidos
0000:7C8F 13161E7C    ADC     DX,[7C1E]            nro de setores escondidos
0000:7C93 03060E7C    ADD     AX,[7C0E]            nro de setores reservados
0000:7C97 83D200      ADC     DX,+00               nro de setores reservados
0000:7C9A A3507C      MOV     [7C50],AX            salva endereço inicial
0000:7C9D 8916527C    MOV     [7C52],DX               do dir raiz (como LBA)
0000:7CA1 A3497C      MOV     [7C49],AX            salva endereço inicial
0000:7CA4 89164B7C    MOV     [7C4B],DX               do dir raiz (como LBA)

                              Determina o endereço de setor do primeiro
                              setor na área de dados como um LBA.

0000:7CA8 B82000      MOV     AX,0020              tamanho de uma entrada de
                                                      diretório (32)
0000:7CAB F726117C    MUL     WORD PTR [7C11]      nro de entradas do
                                                      diretório raiz
0000:7CAF 8B1E0B7C    MOV     BX,[7C0B]            bytes por setor
0000:7CB3 03C3        ADD     AX,BX
0000:7CB5 48          DEC     AX
0000:7CB6 F7F3        DIV     BX
0000:7CB8 0106497C    ADD     [7C49],AX            soma ao endereço inicial
0000:7CBC 83164B7C00  ADC     WORD PTR [7C4B],+00     do dir raiz (como LBA)

                              Transfere o primeiro setor do diretório raiz
                              para 0000:0500.

0000:7CC1 BB0005      MOV     BX,0500              end para transferência
0000:7CC4 8B16527C    MOV     DX,[7C52]            pega end inicial do
0000:7CC8 A1507C      MOV     AX,[7C50]               dir raiz (como LBA)
0000:7CCB E89200      CALL    CONVERT              chama rotina de
                                                      conversão
0000:7CCE 721D        JB      TALK                 salta se houver erro
0000:7CD0 B001        MOV     AL,01                ler 1 setor
0000:7CD2 E8AC00      CALL    READ_SECTORS         lê primeiro setor do
                                                      diretório raiz
0000:7CD5 7216        JB      TALK                 salta se houver erro
0000:7CD7 8BFB        MOV     DI,BX                end da primeira entrada
                                                      do diretório
0000:7CD9 B90B00      MOV     CX,000B              contador é 11
0000:7CDC BEE67D      MOV     SI,7DE6              end dos nomes de arquivos
0000:7CDF F3          REPZ                         é o "IO.SYS"?
0000:7CE0 A6          CMPSB
0000:7CE1 750A        JNZ     TALK                 não
0000:7CE3 8D7F20      LEA     DI,[BX+20]           end da próxima entrada do
                                                      diretório
0000:7CE6 B90B00      MOV     CX,000B              contador é 11
0000:7CE9 F3          REPZ                         é o "MSDOS.SYS"?
0000:7CEA A6          CMPSB
0000:7CEB 7418        JZ      FOUND_FILES          são iguais

	FALA:

                              Mostra mensagem "Non-System disk...",
                              espera usuário apertar uma tecla, restaura
                              o vetro da INT 1E e depois chama a INT 19
                              para iniciar o processo de boot novamente.

0000:7CED BE9E7D      MOV     SI,7D9E              "Non-System disk..."
0000:7CF0 E85F00      CALL    MSG_LOOP             mostra mensagem
0000:7CF3 33C0        XOR     AX,AX                função INT 16
0000:7CF5 CD16        INT     16                   lê teclado
0000:7CF7 5E          POP     SI                   pega o endereço do
0000:7CF8 1F          POP     DS                      vetor da INT 1E
0000:7CF9 8F04        POP     [SI]                 restaura os dados do
0000:7CFB 8F4402      POP     [SI+02]                 vetor da INT 1E
0000:7CFE CD19        INT     19                   chama INT 19 para tentar
                                                      novamente

	PREPARA_FALA:

0000:7D00 58          POP     AX                   tira lixo da pilha
0000:7D01 58          POP     AX                   tira lixo da pilha
0000:7D02 58          POP     AX                   tira lixo da pilha
0000:7D03 EBE8        JMP     TALK                 agora fala com o usuário

	ARQUIVOS_ENCONTRADOS:

                              Trata o endereço de setor do primeiro setor
                              de IO.SYS.

0000:7D05 8B471A      MOV     AX,[BX+1A]           pega nro do cluster
                                                      inicial
0000:7D08 48          DEC     AX                   subtrai 1
0000:7D09 48          DEC     AX                   subtrai 1
0000:7D0A 8A1E0D7C    MOV     BL,[7C0D]            setores por cluster
0000:7D0E 32FF        XOR     BH,BH
0000:7D10 F7E3        MUL     BX                   multiplica
0000:7D12 0306497C    ADD     AX,[7C49]            adiciona o end inicial
0000:7D16 13164B7C    ADC     DX,[7C4B]               do dir raiz (como LBA)

                              Transfere IO.SYS para a memória em 0000:0700.
                              IO.SYS tem comprimento de 3 setores.

0000:7D1A BB0007      MOV     BX,0700              end de transferência
0000:7D1D B90300      MOV     CX,0003              lê 3 setores

	LOOP_DE_LEITURA:

                              Lê os primeiros 3 setores de IO.SYS
                              (IO.SYS muito mais do que 3 setores).

0000:7D20 50          PUSH    AX                   salva AX
0000:7D21 52          PUSH    DX                   salva DX
0000:7D22 51          PUSH    CX                   salva CX
0000:7D23 E83A00      CALL    CONVERT              chama rotina de
                                                      conversão
0000:7D26 72D8        JB      SETUP_TALK           salta se houver erro
0000:7D28 B001        MOV     AL,01                lê um setor
0000:7D2A E85400      CALL    READ_SECTORS         lê um setor
0000:7D2D 59          POP     CX                   restaura CX
0000:7D2E 5A          POP     DX                   restaura DX
0000:7D2F 58          POP     AX                   restaura AX
0000:7D30 72BB        JB      TALK                 salta se erro INT 13
0000:7D32 050100      ADD     AX,0001              soma 1 ao end do setor
0000:7D35 83D200      ADC     DX,+00               soma 1 ao end do setor
0000:7D38 031E0B7C    ADD     BX,[7C0B]            incrementa o end de mem
                                                      com tamanho do setor
0000:7D3C E2E2        LOOP    READ_LOOP            lê próximo setor

                              Deixa informação nos registradoresAX, BX, CX
                              e DX para uso do IO.SYS. Finalmente, salta
                              para o IO.SYS em 0070:000.

0000:7D3E 8A2E157C    MOV     CH,[7C15]            tipo de mídia
0000:7D42 8A16247C    MOV     DL,[7C24]            número do drive
0000:7D46 8B1E497C    MOV     BX,[7C49]            pega o end inicial do
0000:7D4A A14B7C      MOV     AX,[7C4B]               dir raiz (como LBA)
0000:7D4D EA00007000  JMP     0070:0000            salta para 0070:0000

	LOOP_MENSAGEM:

                              Esta rotina mostra uma mensagem usando a
                              INT 10, um caracter por vez.
                              O endereço da mensagem está em DS:SI.

0000:7D52 AC          LODSB                        pega caracter da msg
0000:7D53 0AC0        OR      AL,AL                fim da mensagem?
0000:7D55 7429        JZ      RETURN               salta se sim
0000:7D57 B40E        MOV     AH,0E                mostra um caracter
0000:7D59 BB0700      MOV     BX,0007              atributos de vídeo
0000:7D5C CD10        INT     10                   mostra um caracter
0000:7D5E EBF2        JMP     MSG_LOOP             faça novamente

	CONVERTE:
                              Esta rotina converte um endereço de setor
                              (um LBA) num endereço CHS. O LBA está em
                              DX:AX.

0000:7D60 3B16187C    CMP     DX,[7C18]            parte alta do LBA
                                                      maior que sectPerTrk?
0000:7D64 7319        JNB     SET_CARRY            salta se sim
0000:7D66 F736187C    DIV     WORD PTR [7C18]      divide por
                                                      setores por trilha
0000:7D6A FEC2        INC     DL                   soma 1 ao nro de setores
0000:7D6C 88164F7C    MOV     [7C4F],DL            salva número de setores
0000:7D70 33D2        XOR     DX,DX                zera DX
0000:7D72 F7361A7C    DIV     WORD PTR [7C1A]      div número de cabeças
0000:7D76 8816257C    MOV     [7C25],DL            salva número de cabeças
0000:7D7A A34D7C      MOV     [7C4D],AX            salva nro de cilindros
0000:7D7D F8          CLC                          limpa carry
0000:7D7E C3          RET                          retorna

	SET_CARRY:

0000:7D7F F9          STC                          set carry

	RETORNA:

0000:7D80 C3          RET                          retorna

	LER_SETORES:

                              O chamador desta rotina fornece:
                                 AL = número de setores a serem lidos
                                 ES:BX = localização da mem para
                                         transferência e
                                 CHS endereço da leitura a ser transferida
                                 para as localizações de memória 7C25 e
                                 7C4D a 7C4F.

0000:7D81 B402        MOV     AH,02                INT 13 lê setores
0000:7D83 8B164D7C    MOV     DX,[7C4D]            pega nro de cilindros
0000:7D87 B106        MOV     CL,06                shift contador
0000:7D89 D2E6        SHL     DH,CL                shift esq. cilindro mais
                                                      significativo 6 bits
0000:7D8B 0A364F7C    OR      DH,[7C4F]            OR no número do setor
0000:7D8F 8BCA        MOV     CX,DX                move para CX
0000:7D91 86E9        XCHG    CH,CL                CH=cilindro baixo,
                                                      CL=cilindro alto
                                                      + setor
0000:7D93 8A16247C    MOV     DL,[7C24]            número do drive
0000:7D97 8A36257C    MOV     DH,[7C25]            número da cabeça
0000:7D9B CD13        INT     13                   lê setores
0000:7D9D C3          RET                          retorna

Seguem alguns dados não usados:

0000:7D90 ca86e98a 16247c8a 36257ccd 13c3.... *.....$|.6%|...  *

A mensagem do programa

0000:7D90 ........ ........ ........ ....0d0a *              ..*
0000:7Da0 4e6f6e2d 53797374 656d2064 69736b20 *Non-System disk *
0000:7Db0 6f722064 69736b20 6572726f 720d0a52 *or disk error..R*
0000:7Dc0 65706c61 63652061 6e642070 72657373 *eplace and press*
0000:7Dd0 20616e79 206b6579 20776865 6e207265 * any key when re*
0000:7De0 6164790d 0a00.... ........ ........ *ady...          *

Nomes dos arquivos ocultos

0000:7De0 ........ ....494f 20202020 20205359 *      IO      SY*
0000:7Df0 534d5344 4f532020 20535953 000055aa *SMSDOS   SYS..U.*

A assinatura do setor de boot

Os dois últimos bytes contém a assinatura do setor de boot, 55 AA:

0000:7Df0 ........ ........ ........ ....55aa *              U.*

Considerações finais

Se você conseguiu acompanhar o texto, está na hora de fazer alguma pesquisa. Pegue um editor hexadecimal, dê uma olhada em alguns disquetes, "bootáveis" ou não, e compare os setores de boot. Eu costumo usar o editor WinHex pois, além de outras facilidades, permite visualizar diretamente os setores de discos.

Quero agradecer de público a Hale Landis, especialista em interfaces para dispositivos de armazenamento de dados, autor de vários artigos muito elucidativos - em especial a série de artigos intitulada "How it works". Este módulo é praticamente a tradução de um dos artigos desta série, o "Disassembly of a DOS Floppy Boot Sector". Se tiver um tempinho, visite o site do Hale porque tem muita coisa interessante.


компромат Вадим Логофет квадратная сковородалобановский александр видеохарьков лобановский10 планшетmfxbroker рейтингалександр лобановский

Informações adicionais