OSDev.org
https://forum.osdev.org/

bios not loading bootloader at 0000:7c00
https://forum.osdev.org/viewtopic.php?f=1&t=32542
Page 1 of 1

Author:  4dr14n31t0r [ Sun Nov 05, 2017 2:05 pm ]
Post subject:  bios not loading bootloader at 0000:7c00

I have a boot.asm file with the following content:
Code:
[ORG 0x7c00]
mov ah , 0x0e
mov al ,'X'
int 0x10
jmp 0x7c00

times 510 - ( $ - $$ ) db 0
dw 0xaa55

Then I compile with this command:
Code:
nasm boot.asm -f bin -o boot.bin

and execute in a virtual machine with this command:
Code:
qemu-system-i386 boot.bin

As expected, the screen is filled up with 'X'. However, this doesn't happen when I don't explicitly tell the bootloader to be loaded in 0x7c00 with [ORG 0x7c00]:
Code:
mov ah , 0x0e
mov al ,'X'
int 0x10
jmp 0x7c00

times 510 - ( $ - $$ ) db 0
dw 0xaa55

In the Babystep1 tutorial in OSDev Wiki (http://wiki.osdev.org/Babystep1) says:
Quote:
The CPU starts in real mode and the BIOS loads this code at address 0000:7c00

Why do I have to write
Code:
[ORG 0x7c00]
if the BIOS is supposed to load the code in that location anyways?

Author:  akasei [ Sun Nov 05, 2017 3:36 pm ]
Post subject:  Re: bios not loading bootloader at 0000:7c00 with qemu

Code:
[ORG 0x7C00]

This is for compilator to calculate jumps and labels positions in your code.

Try this:
Code:
[ORG 0x7C00]
main:
   jmp   0x0000:.repair_cs
.repair_cs:
   {your code in here}

Author:  mikegonta [ Sun Nov 05, 2017 3:47 pm ]
Post subject:  Re: bios not loading bootloader at 0000:7c00 with qemu

4dr14n31t0r wrote:
Why do I have to write
Code:
[ORG 0x7c00]
if the BIOS is supposed to load the code in that location anyways?
That's why it has to be done, (so that the assembler knows), otherwise the default is org 0x0000.
Code:
00000000: B4 0E          mov ah , 0x0E
00000002: B0 58          mov al ,'X'
00000004: CD 10          int 0x10
00000006: E9 F7 7B       jmp 0x7C00 ; this jump is relative to 0x0000
Try this:
Code:
00000000: B4 0E           mov ah , 0x0E
00000002: B0 58           mov al ,'X'
00000004: CD 10           int 0x10
00000006: EA 00 7C 00 00  jmp 0x0000:0x7C00 ; this jump is absolute far

Author:  mikegonta [ Sun Nov 05, 2017 3:52 pm ]
Post subject:  Re: bios not loading bootloader at 0000:7c00 with qemu

akasei wrote:
Try this:
Code:
[ORG 0x7C00]
main:
   jmp   0x0000:.repair_cs
.repair_cs:
   {your code in here}
That's only for assemblers which use org for filling in gaps (MASM, TASM, AS).
FASM, for example allows multiple orgs within a file and works the same as NASM to inform the assembler where the code is located.

Author:  4dr14n31t0r [ Sun Nov 05, 2017 5:26 pm ]
Post subject:  Re: bios not loading bootloader at 0000:7c00 with qemu

Sorry I copied and pasted the wrong code. In the first code it should be "jmp 0x7c00" instead of "jmp 0x0". Now that post is edited and fixed.
If I have understood it correctly, when doing that relative jump I was jumping to 0xF800 because 0x7C00 x 2 = 0xF800. Am I correct?

Author:  Schol-R-LEA [ Sun Nov 05, 2017 7:15 pm ]
Post subject:  Re: bios not loading bootloader at 0000:7c00

No, because it isn't a relative jump. The presence of the segment prefix (the 'cs' part) makes it is a 20-bit FAR jump, an absolute jump computed from the segment base and the segment offset by adding them at a 4-bit shift, like so:

Code:
bbbb0
0SSSS
--------
AAAAA


So, for a segment base of 0000 and an offset of 0x7x00, this would be:

Code:
0x00000
0x07c00
--------
0x07c00


However, this addressing system means that segments are no disjoint - for successive bases, the overlap by 16 bytes. This means that the same address can be represented as 0000:7c00, or 0001:7bf0, or 0010:7b00, or 0100:6c00, or even 07c0:0000. I will get to this part more a bit later.

Without the segment prefix, this still wouldn't be an IP-relative jump, however. The CS (Code Segment) segment register is one of four used in real mode, and is the default for code addresses. In real mode, the default JMP instruction without a segment prefix is a 16-bit NEAR jump, which is relative to the segment base address held in CS, not relative to the instruction pointer - that is to say, it is a jump to cs:0x7c00, whatever CS might currently be. This means that the target of a FAR jump with the CS segment prefix is the exact same as a NEAR jump to the same offset - provided that the base in CS is the same as that which is used for the origin of the assembled label being jumped to. Again, I'll get back to this in a moment.

There is an 8-bit SHORT jump, which is a signed IP-relative jump (i.e., it can jump back up to 127 bytes, or forward up to 128 bytes) but with most assemblers, you would need to explicitly state it as SHORT:

Code:
    jmp short .somewhere


Note that conditional jumps in real mode are different - all conditional jumps in the original 8086 were short IP-relative. Also, in 32-bit protected mode, the same opcode is used for 16-bit IP-relative jumps instead.

Now, if the BIOS is properly standards-compliant, at the boot entry point CS should be 0000, which means that if the code is assembled with an origin of 7c00, the code addresses computed by the assembler should. However, that standard didn't get formalized until the late 1990s, specifically as part of the PC98 standard IIRC. Prior to this, most BIOSes did do it that way, but there were a few BIOS implementations which had a different starting CS (usually 07c00, making the entry point the same absolute address but mangling the assembled addresses), which is why many older tutorials on boot loaders recommend that you use a FAR jump to force CS to whatever base you have set the assembled origin at.

That's what the jump you copied there is meant to do, but, well... it shouldn't be needed anymore. Not for any PC-compatible made in the past 20 years, at any rate.

Author:  Brendan [ Sun Nov 05, 2017 8:00 pm ]
Post subject:  Re: bios not loading bootloader at 0000:7c00

Hi,

Schol-R-LEA wrote:
That's what the jump you copied there is meant to do, but, well... it shouldn't be needed anymore. Not for any PC-compatible made in the past 20 years, at any rate.


If someone tries to boot your OS on an ancient computer from 1980 your boot code should behave correctly (e.g. correctly display a "Your CPU is too old" error message without crashing, and correctly halt and wait for user to reboot without crashing). ;)


Cheers,

Brendan

Author:  MichaelFarthing [ Mon Nov 06, 2017 3:28 am ]
Post subject:  Re: bios not loading bootloader at 0000:7c00

I'm not sure what schol-R-Lea meant by "the default jump" in his post, but the example in the OP's code snip:

00000006: E9 F7 7B jmp 0x7C00 ; this jump is relative to 0x0000

though requested as an absolute jump is actually coded as a near jump relative to the next instruction, not the segment base.

It is written by the programmer as if its an absolute jump (to 0x7c00) but the assembler converts this absolute address into a relative one and it is that converted value which appears as the machine coding:

E9 Jmp near relative to next instruction
0x7BF7 relative jump (bytes actually are coded f7 7b in usual Intel convention)
Next instruction is at 0x9
0x9+0x7bf7 = 0x7c00 as requested by the programmer.

This is why the ORG statement is required so that he assembler knows how to convert the absolute address requested to the relative value required in the output code.

Author:  iansjack [ Mon Nov 06, 2017 3:37 am ]
Post subject:  Re: bios not loading bootloader at 0000:7c00

I'm not sure that this has been made sufficiently clear:

The ORG directive is not telling the computer where to load the program. It is the other way round - the ORG directive is telling the assembler that this is where the program will be loaded. (It's always loaded at that address, whatever ORG directives you use.)

Author:  4dr14n31t0r [ Mon Nov 06, 2017 4:13 am ]
Post subject:  Re: bios not loading bootloader at 0000:7c00

Sorry for the misunderstanding. mikegonta wrote in Sun Nov 05, 2017 3:47 pm this code:
Code:
00000000: B4 0E          mov ah , 0x0E
00000002: B0 58          mov al ,'X'
00000004: CD 10          int 0x10
00000006: E9 F7 7B       jmp 0x7C00 ; this jump is relative to 0x0000

And then I wrongly said 'relative jump' but I mean relative to 0x0000

Author:  Schol-R-LEA [ Mon Nov 06, 2017 8:40 am ]
Post subject:  Re: bios not loading bootloader at 0000:7c00

MichaelFarthing wrote:
I'm not sure what schol-R-Lea meant by "the default jump" in his post,


I meant a JMP instruction without adding an explicit SHORT/NEAR/FAR modifier, in MASM/NASM syntax. That assumption of MASM syntax was careless of me.

MichaelFarthing wrote:
but the example in the OP's code snip:


This was careless of me, too. I had gotten turned around and was looking at the code snippets given by akasei and MikeGonta, both of which used absolute FAR jumps on a constant immediate segment base, then somehow go further confused and started thinking that they were using 'cs:' as the base instead of '0x0000'.

Page 1 of 1 All times are UTC - 6 hours
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
http://www.phpbb.com/