My second stage boot loader works but when i print a message, it just shows a blank screen. When I do it with the boot loader, it works. Heres my code.

boot.asm

Code:

bits 16org 0x7c00

Main:mov ax, 0x7e00mov es, axmov bx, 0

mov ah, 2mov al, 1mov ch, 0mov cl, 2mov dh, 0mov dl, 0int 13h

jmp 0x7e00:0000

clihlt

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

kernel.asm

Code:

bits 16org 0x7e00

jmp main

main:mov si, msgcall print

print:lodsbcmp al, 0je donemov ah, 0ehint 10hjmp print

done:ret

clihlt

I've tried to troubleshoot. I tried changing the address the code is put in memory. I have seen a message with an equal sign and a S. What seems to be the problem? Sorry, I have took a break from OSDev :/

_________________Computers aren't to blame... the ones who program them are.

well first there are problems with your bootsector... it won't work on real hardware (though it will probably work on emulators most of the time)

but ignoring that... you haven't defined msg anywhere (that I can see) -- are you sure its set correctly? (your description of the problem sounds suspiciously like printing a nullptr)

also:your code is broken: it should print the string, and then start running random memory

first you are calling the print function (seems correct as long as your pointer is correct)

then you are returning and falling through into... the same print function you just called (this will actually work correctly, and will print whatever happens to be in SI... probably whatever is after the string that you printed first)

but then your print function returns... but since it wasn't called, you will return to whatever happened to be on the stack before... which means you will be returning to random memory and executing random data (very not good... and on real hardware it may damage the computer)

I think you may misunderstand how real mode segmentation works. The physical address is (segment*16)+offset or it can be written as (segment<<4)+offset

0x7e00:0x0000 is actually physical address (0x7e00<<4)+0x0000 which is 0x7e000 . I don't believe that is what you want. It looks like you really want to us 0x0000:0x7e00 which is (0x0000<<4)+0x7e00 = physical address 0x7e00. You'll want to set up ES:BX for the disk read as ES=0x0000 and BX=0x7e00 as well.

When the BIOS transfers control to your bootloader it will set DL to the drive umber that is booted. You should not use the value of 0 (always Floppy A) when doing disk reads from the boot media. You should use the value in DL passed to the bootloader.

Your final CLI/HLT sequence should be moved so it appears after the call to print so that it doesn't fall into your print function.

You should also never assume ES and DS are set to what you expect. You should always explicitly load them with the values you need. You should also set up the stack pointer (SS;SP) yourself.

I think you may misunderstand how real mode segmentation works. The physical address is (segment*16)+offset or it can be written as (segment<<4)+offset

0x7e00:0x0000 is actually physical address (0x7e00<<4)+0x0000 which is 0x7e000 . I don't believe that is what you want. It looks like you really want to us 0x0000:0x7e00 which is (0x0000<<4)+0x7e00 = physical address 0x7e00. You'll want to set up ES:BX for the disk read as ES=0x0000 and BX=0x7e00 as well.

When the BIOS transfers control to your bootloader it will set DL to the drive umber that is booted. You should not use the value of 0 (always Floppy A) when doing disk reads from the boot media. You should use the value in DL passed to the bootloader.

Your final CLI/HLT sequence should be moved so it appears after the call to print so that it doesn't fall into your print function.

You should also never assume ES and DS are set to what you expect. You should always explicitly load them with the values you need. You should also set up the stack pointer (SS;SP) yourself.

ive tried using 0x7c00 and that work but 0x7e00 doesnt. Why's that?

_________________Computers aren't to blame... the ones who program them are.

ok, your jumping to 0x7E00:0000 is actually correct... but many other things aren't, let me try to give a partial list:

for your bootsector:1)

Code:

int 13h

you haven't set up your stack yet -- the stack the BIOS was using is not guaranteed to be valid (for practical reasons it probably will be, but you really are supposed to set up a stack before using it)

2)

Code:

int 13h

jmp 0x7e00:0000

this will likely work most of the time on most emulators, but will not work on real hardware -- in reality, any time you read from the disk you need to be prepared for read errors and retry the disk read -- this is especially true for the FDD

3)

Code:

clihlt

this isn't really an error but it is unnecessary (since the jmp transfers execution elsewhere)

this code could be rewritten better by adding a stack setting code, and then adding code to retry the disk read if the read function returns an error

for your 2nd stage:4)

Code:

org 0x7e00

this is actually wrong: it should be org 0

the org value is added to addresses by the assembler, and thus should be set to the offset to be added -- the starting offset from DS (not CS, and not the segment)

5)

Code:

jmp main

main:

not really an error, but completely unnecessary6)

Code:

mov si, msg

where is msg defined? I see it nowhere in the code you posted... most likely this is zero (as that would explain the symptoms you described)

7)

Code:

call print

print:

this works, but it does something unexpected... after calling print, it returns and continues executing here... making it execute print again, this time with SI pointing after the end of your previous string (this will print whatever garbage happened to be in memory after your string...)

to this point this code actually works however, but it causes this error here:

8 )

Code:

ret

this isn't an error itself, but because of problem #7, it becomes an errror...

the first time print is called this works correctly, however because you drop into the print function after returning from the print function this ret returns to whatever was on the stack before... which means you now loose control of the CPU

worse, the CPU will continue executing random instructions from random memory until it gets to an instruction that reads/writes a hardware device, and by doing so sets that device to a bad setting which destroys the computer

while this might not happen, it will certainly not do what you want it to do

9) -- this one is out of order because of the relation between the previous 2

Code:

lodsb

this instruction isn't doing what you think it is -- you haven't set DS, therefore you aren't taking the message from wherever you have it (its not anywhere in the code you posted) but rather taking it from the address 7e00 (your org statement) + offset-of-message-in-file + whatever_DS_base_happens_to_be_set_to...

this 2nd stage could be better rewritten by:change org to 0be sure to place the message in the same file with the 2nd stageset DS as appropriate so it can reach your 2nd stage (where the data is)move your

Code:

clihlt

up to be between the

Code:

call print

line and the

Code:

print:

line

if you make the changes and fixes I described here, your code should work

edit:do note that some emulators halt execution when they find a HLT instruction with IF=0 (like your cli;hlt instruction pair you have been using) -- sometimes this will happen before the printed text is actually displayed to the screen, if this happens replacing the cli;hlt instruction block with:

there are only 4 possibilities:1) you are not storing your 2nd stage in the correct place on the disk (I don't know how you are doing it, so obviously I don't know if you are doing it correctly)2) you are not actually loading the 2nd stage (the int 13h call is returning an error and not loading the sector at all) -- probably not the case if your using an emulator (but definitely the case if your using a real FDD on a real computer -- see #2 on my previous list)3) you are not properly defining your string

or, you are correctly defining the string and loading the 2nd stage... in that case we know for sure what the problem is:4) you are not properly setting up DS (see #9 on the list I previously posted)

note that #4 will prevent it from printing regardless of anything else that may be wrong, it must be fixed before it can work

do note that it printing correctly from the bootsector but not from the 2nd stage is a symptom of not setting DS (it will work in the bootsector on some computers but not on other computers, and never from the 2nd stage)

I highly recommend that you go through my previous post carefully, fix everything I mentioned, then if it still doesn't work post again and include the full (not partial, must include everything in the files -- including the definition of your string), fixed, code

there are only 4 possibilities:1) you are not storing your 2nd stage in the correct place on the disk (I don't know how you are doing it, so obviously I don't know if you are doing it correctly)2) you are not actually loading the 2nd stage (the int 13h call is returning an error and not loading the sector at all) -- probably not the case if your using an emulator (but definitely the case if your using a real FDD on a real computer -- see #2 on my previous list)3) you are not properly defining your string

or, you are correctly defining the string and loading the 2nd stage... in that case we know for sure what the problem is:4) you are not properly setting up DS (see #9 on the list I previously posted)

note that #4 will prevent it from printing regardless of anything else that may be wrong, it must be fixed before it can work

do note that it printing correctly from the bootsector but not from the 2nd stage is a symptom of not setting DS (it will work in the bootsector on some computers but not on other computers, and never from the 2nd stage)

I highly recommend that you go through my previous post carefully, fix everything I mentioned, then if it still doesn't work post again and include the full (not partial, must include everything in the files -- including the definition of your string), fixed, code

I think it's the segmented addressing. Why does my second stage bootloader print a message if it is loaded at 0x7c00 but not 0x7e00? It's not any of these 'bad practices' much. It's the fact that using 0x7e00 doesn't seem to work. I just don't understand why.

_________________Computers aren't to blame... the ones who program them are.

I think it's the segmented addressing. Why does my second stage bootloader print a message if it is loaded at 0x7c00 but not 0x7e00?

as I said, the reason it does print the message if it is loaded at 0x7C00 but doesn't print the message if it is loaded at 0x7E000 is because you haven't set the DS register properly

additionally, if you run it on different computers, on some computers it will print the message if loaded at 0x7C00 and on other computers it won't print the message when loaded at exactly the same address!

in theory it is actually possible that it will print the message correctly when loaded at 0x7E00:0 on some computers! (but not on most computers) but on those computers it will not print the message if it is loaded at 0x7C00

when you run the "lodsb" instruction, the CPU fetches a byte from memory at the address specified by the register combination DS:SI -- you have set SI to the address of the message you want to print, but you left whatever random data the firmware happened to have in DS before calling your bootsector in DS... so obviously this isn't going to work correctly...

therefore, as I have been saying for the last 3 posts now, I will repeat yet again: set DS register correctly and it will automatically start working on some emulators (if you don't fix the rest of the errors I mentioned, it won't work on any real hardware, and will fail on some emulators as well)

Quote:

It's not any of these 'bad practices' much.

none of what I mentioned are "bad practices"... 7 of them are outright errors that will cause it to not work (2 of them are not errors, just unnecessary) -- and one of them (#8 on my list) can actually destroy the computer it is running on (physically damage the hardware such that the computer can never run again and must be thrown in the garbage and replaced with a new computer)

Quote:

It's the fact that using 0x7e00 doesn't seem to work. I just don't understand why.

... you are not actually using address 0x7E00... you are using address 0x7E000 (note the extra zero) -- and it doesn't matter at all what address you use, if you don't set DS correctly it will not work (on the particular emulator you are using, it happens to work at address 0x7C00... but that isn't true for all computers)

in RMode, the segment is multiplied by 16 (moved to the left 1 hexidecimal position) and added to whatever offset address you use

so when you specify a 16bit address (such as SI in the lodsb instruction) where does the CPU get the segment from? from the DS register... which you haven't set to anything and left whatever garbage value the BIOS had in that register before you ran it... and that is not going to work

on the particular emulator you happen to be testing this on, this value happens to contain a 0 (which is why it works when you try to print from 0x7C00) but this is not true for other computers or emulators -- regardless, you must always set DS before using any data (such as your string) always -- this is not "best practices", this is not "you should", this is not "you might want to", the is must because it will not work at all if you don't

edit:really, fixing the 7 errors I pointed out will cause your code to magically start working, not only on the emulator you are using, but on all emulators and real hardware, and shouldn't be hard to do -- it should take you less time to make those fixes than it took me to write this post

I think it's the segmented addressing. Why does my second stage bootloader print a message if it is loaded at 0x7c00 but not 0x7e00?

as I said, the reason it does print the message if it is loaded at 0x7C00 but doesn't print the message if it is loaded at 0x7E000 is because you haven't set the DS register properly

additionally, if you run it on different computers, on some computers it will print the message if loaded at 0x7C00 and on other computers it won't print the message when loaded at exactly the same address!

in theory it is actually possible that it will print the message correctly when loaded at 0x7E00:0 on some computers! (but not on most computers) but on those computers it will not print the message if it is loaded at 0x7C00

when you run the "lodsb" instruction, the CPU fetches a byte from memory at the address specified by the register combination DS:SI -- you have set SI to the address of the message you want to print, but you left whatever random data the firmware happened to have in DS before calling your bootsector in DS... so obviously this isn't going to work correctly...

therefore, as I have been saying for the last 3 posts now, I will repeat yet again: set DS register correctly and it will automatically start working on some emulators (if you don't fix the rest of the errors I mentioned, it won't work on any real hardware, and will fail on some emulators as well)

Quote:

It's not any of these 'bad practices' much.

none of what I mentioned are "bad practices"... 7 of them are outright errors that will cause it to not work (2 of them are not errors, just unnecessary) -- and one of them (#8 on my list) can actually destroy the computer it is running on (physically damage the hardware such that the computer can never run again and must be thrown in the garbage and replaced with a new computer)

Quote:

It's the fact that using 0x7e00 doesn't seem to work. I just don't understand why.

... you are not actually using address 0x7E00... you are using address 0x7E000 (note the extra zero) -- and it doesn't matter at all what address you use, if you don't set DS correctly it will not work (on the particular emulator you are using, it happens to work at address 0x7C00... but that isn't true for all computers)

in RMode, the segment is multiplied by 16 (moved to the left 1 hexidecimal position) and added to whatever offset address you use

so when you specify a 16bit address (such as SI in the lodsb instruction) where does the CPU get the segment from? from the DS register... which you haven't set to anything and left whatever garbage value the BIOS had in that register before you ran it... and that is not going to work

on the particular emulator you happen to be testing this on, this value happens to contain a 0 (which is why it works when you try to print from 0x7C00) but this is not true for other computers or emulators -- regardless, you must always set DS before using any data (such as your string) always -- this is not "best practices", this is not "you should", this is not "you might want to", the is must because it will not work at all if you don't

edit:really, fixing the 7 errors I pointed out will cause your code to magically start working, not only on the emulator you are using, but on all emulators and real hardware, and shouldn't be hard to do -- it should take you less time to make those fixes than it took me to write this post

Do you mean put in the second stage bootloader this?

Code:

mov ax, 0x7e00mov ds, ax

When I do that, it still shows nothing.

Yes, I understand LODSB simply takes a byte from DS:(E)SI, puts into AL and does increment to the address. STOSB stores a byte from AL to ES:(E)DI.

Yes, I have got msg defined in the second stage bootloader.

Should it be 0x07e0 or 0x7e00?

The second stage bootloader can actually print a character (INT 10h -> function 0eh with AL=char) but it can't print a message. It's getting on my nerves... I'm using Virtualbox by the way. I'm not using real hardware. I might do soon.

UPDATE: When I use org 0x7c00 on my second stage, it actually prints the message. I want 0x7e00 because 0x7c00 is the bootloader and I don't want to overwrite it. I've also tried 0x1000. That doesn't print the message.

I'm getting sick and tired of this. My code is terrible. I've set DS correctly to 0x1000 0x7e00 this that.The only way to even get a little gibberish printing out would be to change ORG. How do I get my message to 0x7e00?

_________________Computers aren't to blame... the ones who program them are.

Who is online

Users browsing this forum: Majestic-12 [Bot] and 3 guests

You cannot post new topics in this forumYou cannot reply to topics in this forumYou cannot edit your posts in this forumYou cannot delete your posts in this forumYou cannot post attachments in this forum