为什么bios将mbr装载到0x7c00地址,0x7c00怎么来的?

1 篇文章 0 订阅

Do you know "0x7C00", a magic number, in x86 assembler programming ?
"0x7C00" is the memory address which BIOS loads MBR(Master Boot Record, a first sector in hdd/fdd) into. OS or bootloader developer must assume that their assembler codes are loaded and start from 0x7C00.

But...1st, you may wonder.

"I read all of Intel x86(32bit) programmers manual, but did not found the magic number 0x7C00."

Yes.0x7C00 is NOT related to x86 CPU. It's natural that you couldn't find out it in cpu specifications from intel. Then, you wonder, "Who decided it ?"

2nd, you may wonder:

"0x7C00 is 32KiB - 1024B at decimal number. What's this number means ?"

Anyone decided it. But, why he/she decided such a halfway address?

Hum...There're TWO questions(mysteries) arround the magic number "0x7C00".

  1. Who decided "0x7C00" ?
  2. What "0x7C00 = 32KiB - 1024B" means ?

Okay, let's dive into the secret of BIOS for "IBM PC 5150", ancestor of modern x86(32bit) PCs, with me...!!

"0x7C00" First appeared in IBM PC 5150 ROM BIOS INT 19h handler.

Wandering arround the history of x86 IBM Compatible PC, you know IBM PC 5150 is the ancestor of modern x86(32bit) IBM PC/AT Compatible PCs.
This PC was released at 1981 August, with Intel 8088(16bit) and 16KiB RAM(for minimum memory model). BIOS and Microsoft BASIC was stored in ROM.

When power on, BIOS processes "POST"(Power On Self Test) procedure, and after, call INT 19h.
In INT 19h handler, BIOS checks that PC has any of floppy/hard/fixed diskette or not have.
If PC has any of available diskkete, BIOS loads a first sector(512B) of diskette into 0x7C00.

Now, you understand why you couldn't find out this magic number in x86 documents. This magic number belongs to BIOS specification.

The origin of 0x7C00

Stories surrounding IBM PC DOS, Microsoft, and SCP's 86-DOS are famous stories. See: "A Short History of MS-DOS".

SCP's "86-DOS"(at 1980) is the reference OS for IBM PC DOS 1.0.
86-DOS(early called "QDOS") is CP/M compatible OS for 8086/8088 cpu. At 1979, Digital Research Inc didn't have developed CP/M for 8086/8088 cpu yet.

SCP sold two S-100 bus board, one is 8086 CPU board, two is "CPU Monitor" rom board.
"CPU Monitor" program provided bootloader and debugger. This "CPU Monitor" bootloader loaded MBR into "0x200", NOT "0x7C00". In 1981, IBM PC DOS was the NEXT CP/M like OS for 8086/8088.

So, I told you that "0x7C00 FIRST appeared in IBM PC 5150 ROM BIOS".
Previous one, SCP's CPU Monitor bootloader loads into 0x200, not 0x7C00.

Why that CPU Monitor's bootloader loeded MBR into "0x200" ?

There're THREE reasons about "0x200".

  1. 8086 Interrupts Vector use 0x0 - 0x3FF.
  2. 86-DOS was loaded from 0x400.
  3. 86-DOS didn't use interrupts vectors between 0x200 - 0x3FF.

These reasons mean 0x200 - 0x3FF needed to be reserved and couldn't be in the way of an OS, no matter where 86-DOS or user application wanted to load.

So Tim Paterson (86-DOS developer) chose 0x200 for MBR load address.

Q:Who decided "0x7C00" ? - A: IBM PC 5150 BIOS Developer Team.

"0x7C00" was decided by IBM PC 5150 BIOS developer team (Dr. David Bradley).
As mentioned above, this magic number was born at 1981 and "IBM PC/AT Compat" PC/BIOS vendors did not change this value for BIOS and OS's backward compatibility.

Not Intel(8086/8088 vendor) nor Microsoft(OS vendor) decided it.

Q:What "0x7C00 = 32KiB - 1024B" means ? A: Affected by OS requirements and CPU memory layout.

IBM PC 5150 minimum memory model had only 16KiB RAM. So, you may have a question.

"Could minimum memory model (16KiB) load OS from diskette ? BIOS loads MBR into 32KiB - 1024B address, but physical RAM is not enough..."

No, that case was out of consideration. One of IBM PC 5150 ROM BIOS Developer Team Members, Dr. David Bradley says:

"DOS 1.0 required a minimum of 32KB, so we weren't concerned about attempting a boot in 16KB."

(Note: DOS 1.0 required 16KiB minimum ? or 32KiB ? I couldn't find out which correct. But, at least, in 1981's early BIOS development, they supposed that 32KiB is DOS minimum requirements.)

BIOS developer team decided 0x7C00 because:

  1. They wanted to leave as much room as possible for the OS to load itself within the 32KiB.
  2. 8086/8088 used 0x0 - 0x3FF for interrupts vector, and BIOS data area was after it.
  3. The boot sector was 512 bytes, and stack/data area for boot program needed more 512 bytes.
  4. So, 0x7C00, the last 1024B of 32KiB was chosen.

Once OS loaded and started, boot sector is never used until power reset. So, OS and application can use the last 1024B of 32KiB freely.

After OS loaded, memory layout will be:

+--------------------- 0x0| Interrupts vectors+--------------------- 0x400| BIOS data area+--------------------- 0x5??| OS load area+--------------------- 0x7C00| Boot sector+--------------------- 0x7E00| Boot data/stack+--------------------- 0x7FFF| (not used)+--------------------- (...)

That are the origin and reasons of "0x7C00", the magic number survived for about three decades in PC/AT Compat BIOS INT 19h handler.

References

86-DOS related:

  • "8086 Monitor Instruction Manual"(MON 86 - V1.4)
  • "86-DOS(TM) User's Manual Version 0.3"
  • "86-DOS(TM) Programmer's Manual Version 0.3"
  • "86-DOS(TM) Instruction Manual Version ??"

IBM PC 5150 related:

  • "IBM Personal Computer Hardware Reference Library", "Technical Reference" (IBM Personal Computer Technical Reference manual)
  • "IBM Personal Computer XT Hardware Reference Library", "Technical Reference" (IBM Personal Computer XT Technical Reference manual)

Intel 8086/8088 data sheets:

  • "8086 16-BIT HMOS MICROPROCESSOR"
  • "M80C86/M80C86-2 16-BIT CHMOS MICROPROCESSOR"
  • "8088 8-BIT HMOS MICROPROCESSOR"

CP/M related:

86-DOS related:

And all related Wikipedia pages.

Special Thanks To...

Special Thanks To:

  • Tim Peterson
  • David Bradley
for japanese article, see:
"Assembler/なぜx86ではMBRが"0x7C00"にロードされるのか?(完全版)"
http://www.glamenv-septzen.net/view/614
好的,以下是修改后的程序: ``` org 0x7c00 ; 告诉汇编器这是一个MBR程序,并将其加载到0x7c00处 mov ah, 0x0e ; 设置打印模式 mov al, 'X' ; 打印你的姓名拼音 int 0x10 ; 调用BIOS中断打印字符 mov al, 'X' int 0x10 mov al, 'X' int 0x10 mov al, 'X' int 0x10 mov al, '1' ; 打印你的学号 int 0x10 mov al, '2' int 0x10 mov al, '3' int 0x10 mov al, '4' int 0x10 mov al, '5' int 0x10 mov al, '6' int 0x10 mov bx, 0x7c00 ; 将bx指向程序的起始地址 mov cx, 18 ; 设置要计算的字符总数为18 mov dx, 0 ; 初始化结果寄存器 sum_loop: add dl, byte [bx] ; 将当前字符的ASCII值加到dx寄存器中 inc bx ; 将bx指向下一个字符 loop sum_loop ; 重复执行,直到所有字符都被处理 mov ah, 0x0e ; 设置打印模式 mov al, ' ' ; 打印一个空格 int 0x10 add dl, 144 ; 将寄存器值加上144,以将其转换为ASCII字符 mov al, dl ; 将结果存储到al寄存器中 int 0x10 ; 调用BIOS中断打印字符 mov al, ':' int 0x10 mov ah, 0 ; 设置中断号为0x10,功能为获取键盘输入 int 0x16 ; 等待用户按下任意键 jmp $ ; 无限循环 times 510-($-$$) db 0 ; 填充剩余的空间,使程序大小为512字节 dw 0xaa55 ; MBR标识 ``` 主要修改如下: 1. 在计算结果并打印时,我们使用了不同的方式来将结果转换为ASCII字符。具体来说,我们首先使用`add dl, 144`指令将寄存器值加上144,然后将结果存储回dl寄存器中。接下来,我们将dl寄存器中的值存储到al寄存器中,并使用`int 0x10`指令调用BIOS中断以在屏幕上打印结果。 2. 我们删除了名字和学号之间的空格,同时将打印冒号的指令移动到了打印结果的指令之后,以确保结果和冒号之间没有空格。 请注意,这个程序仍然是非常基础的,只是一个简单的示例程序,并且未经过充分测试。在实际使用中,您可能需要进行更多的测试和错误处理,以确保程序可以正确地运行。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值