Bugy Code

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
yannkir

Bugy Code

Post by yannkir »

Could you please tell me what's wrong with this code? I just can't find it out. It loads OK(trust me, I testet it with a nother function), but it won't display a string.
code
[BITS 16]
[ORG 0x2C00]
cli
mov ax,0xFFFF
mov sp,ax
mov ax,0x2C00
mov ss,ax
xor ax,ax
mov ds,ax
sti
jmp startrealk
printstringk:
mov ah,13
mov al,0x01
mov bh,0x00
mov bl,0x07
int 0x10
ret
startrealk:
mov es,[message1]
mov bp,message1
mov cx,0x3
call printstringk
message1 db 'Hi',0
code end
Schol-R-LEA

Re:Bugy Code

Post by Schol-R-LEA »

In the absence of other information, I'm assuming that this is a boot loader; if it isn't, then we'll need more context before we can help you with it.

First off, your origin should be 0x7C00, not 0x2C00. While the code may load correctly, the addresses will be all wrong as a result.

Second, you have to keep in mind that while ORG sets the segment offset, [tt]mov ss, ax[/tt] sets the segment base. In this case,

[ORG 0x7C00] == 0000:7C00 == 07C00:0000

whereas

Code: Select all

mov ax, 0x7C00
mov SS, ax
== 7C00:0000

If you want to set the stack and data segment bases to match the code segment, the best solution is to use

Code: Select all

mov ax, cs
mov ss, ax
mov ds, ax
For that matter, since not all BIOSes follow the standards, it would be wise to reset the code segment and offest explicitly at the beginning of the code, like this:

Code: Select all

entry: jmp far [0000:start]

start:
          cli
           ...
Third, There's no real ending to your code; after printstringk returns, the program just sort of walks off then end of the code. You'll want to add some kind of busy loop, like so:

Code: Select all

jmp short $
Where the dollar sign is a special directive meaning 'the current address'.

Finally, you don't include the Boot Signature, a special word-sized indicator (0x55AA) at the end of the boot block which marks it as valid. To add this, you need to pad out the data to 2 bytes before the end of the book block; since the boot block is 512 bytes in length, you would need to use:

Code: Select all

(510 - $ - $$) times db 0
Where, '$$' is a directive meaning 'the beginning of the program'. This is followed by the boot signature itself:

Code: Select all

bootsig db 0x55AA

Oh, and BTW, the tags for starting and ending a block of code in YaBBcode are [ code ] and [ /code ], without the spaces. HTH.
bkilgore

Re:Bugy Code

Post by bkilgore »

is this bootloader code? I'm wondering about the org 2c00. If this is bootloader code

Code: Select all

mov es,[message1]
mov bp,message1

will have problems with the offset. Also, what exactly doesn't work? What happens? Becuase after you return from "call printstringk" it seems like there would be invalid code there. Also, you never initialize dh and dl before the int10 to specify the row and column. If this is bootloader code, not only is dx not guaranteed to be 0, but iirc dl will be the drive that was booted.
Yann KIraly

Re:Bugy Code

Post by Yann KIraly »

No, it isn`t the bootloader. It is loaded at 2c00. But thanks, i`ll try that out right away.
Schol-R-LEA

Re:Bugy Code

Post by Schol-R-LEA »

In that case, it may help if you could answer some questions:

[*] How is the code being loaded, and from what? I am assuming that, since it is not the bootloader itself, it is the kernel or second stage loaded by the bootloader (presumably the former, since the function names end in 'k' - I'd missed that before).

[*] How are you transferring control to the program, with a jump or a call, and was it NEAR or FAR?

[*] What is the full address transferred to - 0000:2C00, or 02C0:0000, or 2C00:0000? Is there a particular reason for that location?

[*] If this is the kernel, are you certain that you want to have the stack in the same segment as the code and data?

Hopefully, this will help us with your problems.
Yann Kiraly

Re:Bugy Code

Post by Yann Kiraly »

First, I'D like to thank you guys for giving so mutch atention to a newbee like me. Now to your questions.
It is the kernel. It is loaded with: jmp 2000:0000.
I chose this location, because I don`t need much space for the kernel(only 8k) and it is an empty part of memory.
Yann kiraly

Re:Bugy Code

Post by Yann kiraly »

And I don`t have to have the stack in this segment. I only thought it is the only way of doing it.
Schol-R-LEA

Re:Bugy Code

Post by Schol-R-LEA »

Yann Kiraly wrote: First, I'D like to thank you guys for giving so mutch atention to a newbee like me. Now to your questions.
It is the kernel. It is loaded with: jmp 2000:0000.
I chose this location, because I don`t need much space for the kernel(only 8k) and it is an empty part of memory.
Ah, then there is part of your problem: in real mode, the origin statement only applies to the segment offset, not the segment base or the linear address. Since your offset is 0x0000, then you need your origin to be 0x0000 as well.


If you need a deeper explanation of segment arithmetic, see Perica Senjak's real mode addressing tutorial, and review these threads:
Replies #11 and #23
Reply #24
Reply #4
Reply #2

Don't worry too much if it seems confusing right now; segmented addressing is one of the most difficult aspects of the x86 architecture to understand. It only gets worse in protected mode, I'm afraid, though there are some workarounds there that make things easier. In real mode, no such shortcut is available, so you really do need to undertand it.
Yann Kiraly

Re:Bugy Code

Post by Yann Kiraly »

I took a different aproach loading my (with your help corrected) Kernel from the FAT filesystem.Thanks. And now I wanted to ask how a kernel and bootloader can be written to an unformated floppy using Windows with rawwrite or Linux?
Post Reply