Page 1 of 1

strange error in MBR code for UFD

Posted: Thu Jun 28, 2007 7:01 am
by SolidSnake
I'm trying to write simple "Hello world" code on MBR/sector 1 in my USB Flash Drive (UFD). I'm using TASM 5.0 and then manually, extracting the code portion from the *.EXE and pasting it into sector 1 of UFD using disk editor.
But I got strange results. The screen showing something like "Hel@". The same code, if written under harddisk bootarea (first sector of partition), can run properly.
Strangely, everything is okay if I'm not using Jump or JXXX in my code.
Currently, I'm using option "USB-ZIP" as my first boot device. "USB-HDD" and others won't work. Is there something I need to do to boot from UFD properly?

Posted: Mon Jul 02, 2007 11:53 am
by hailstorm
Can you post your bootcode? That gives us more information... :D

Posted: Tue Jul 03, 2007 5:07 am
by SolidSnake
It was something like:

Code: Select all

     LEA   SI, HELLO
     MOV  AH, 0EH    
L1:
     LODSB
     OR    AL, AL
     JZ     HANG
     INT   10H
     JMP   L1

HANG:  JMP HANG

HELLO  DB  'Hello Words!',0
When I boot my PC, it just show something like: "Hel@" and then hang (sometimes I even can't press Ctrl+Alt+Del, but I don't CLI).
The same code run properly if written under my harddisk partition. I don't know what is happening here...[/code]

Posted: Tue Jul 03, 2007 6:05 am
by hailstorm
Hmmm. Ok, your code is fine, but I have the feeling that you don't know what is happening before your code starts.
Please keep in mind that the bios puts your code at 0x7c00 in memory, with al segment registers set to 0. So, before you can use a string in assembly while booting, you must do the following:
Compile your code using org 0x7c00.
Or
Initialize es and / or ds to 0x7c0.

Also don't forget to put the number 0x55aa at byte 510 in your code.

I hope this helps, if it doesn't, I am sure a lot of other people know how to help you with your problem.

Greetz.

Posted: Wed Jul 04, 2007 6:53 am
by SolidSnake
Oops.. I forget to include the initilization here.. I have wrote the stack initialization (set SS to 0 and SP to 7C00H) and set DS to 0 also include ORG 7C00H..

But, coz I'm new and using TASM 5.0, after compile and linking, I manually extract the machine code from the DOS EXE format. I remember it was starting at offset 7E00H.. Is it okay? Anyway, I really like to know if I have easier way to do that in TASM 5.0 dan TLINK 5.1. May be there's some arguments to pass in command prompt?

Thanks for the help, bro.

Posted: Wed Jul 04, 2007 7:29 am
by Brendan
Hi,
SolidSnake wrote:Oops.. I forget to include the initilization here.. I have wrote the stack initialization (set SS to 0 and SP to 7C00H) and set DS to 0 also include ORG 7C00H..

But, coz I'm new and using TASM 5.0, after compile and linking, I manually extract the machine code from the DOS EXE format. I remember it was starting at offset 7E00H.. Is it okay? Anyway, I really like to know if I have easier way to do that in TASM 5.0 dan TLINK 5.1. May be there's some arguments to pass in command prompt?
This makes me wonder if your initialization code started with something like "jmp 0x0000:start", which didn't work because TASM encoded it as "jmp 0x0000:0x7E??".

Anyway, TASM is "unmaintained" (or as some people call it, abandonware) - TASM 5.0 is at least 10 years old, and AFAIK doesn't support any of the new instructions (3DNOW, MMX, SSE, etc). I'd also assume that if you ever want to port it to your OS you'll have trouble.

There's plenty of good free open source assemblers (NASM, YASM, FASM, etc). It's probably better to switch assemblers now, instead of trying to figure out how to stop TASM from generating DOS executables (and then switching to a more modern assembler later anyway)... ;)


Cheers,

Brendan

Posted: Wed Jul 04, 2007 7:47 am
by hailstorm
The value 7e00h doesn't supprise me at all. You see, tasm compiles an exe and this is DOS executable. These executables always contain a header 512 bytes, which is ofcourse 0200h.
If I were you, I wouldn't compile the executable as an EXE, but as a com-file.
Or even better. Start your program by initializing ds, es and ss to 07C0H. Then, let the assembler know you are starting at address 0, by using ORG 0 right after segment declaration, or .CODE, whatever you are using.

Code: Select all

NEW_SEGMENT     =       07C0H
STACK_POINTER   =       03FEH
MAGIC1          =       02004H
MAGIC2          =       0502H

jmpfa   MACRO seg, ofs
          db 0eah
          dw ofs, seg
        ENDM

_TEXT SEGMENT PARA PUBLIC 'CODE'
ASSUME CS:_TEXT, DS:_TEXT
jmp		start
	db	'Hailos01'
	dw	512
	db	1
	dw	1
	db	2
	dw	224
	dw	0
	db	0f0h
	dw	2880
	
start:
  mov   ax, NEW_SEGMENT
  mov   ds, ax
  mov   es, ax
  cli                           ; Disable interrupts, very important!
  mov   ss, ax                  ; Set the stacksegment
  mov   sp, STACK_POINTER       ; Set the stackpointer
  sti                           ; Enable interrupt flag.

NEW_OFS        =       offset re_enter
  jmpfa NEW_SEGMENT, NEW_OFS
re_enter:
  blah and code so on.
Although TASM is abandonware, for bootsector programming it is an excelent assembler.

Posted: Thu Jul 05, 2007 6:10 am
by SolidSnake
Oh, i see.. Thanks all for the info.. I'm still new in OS programming, and all I know is some programming in TASM and C/C++.. I can't compile them into COM coz looks like TLINK want me to use ORG 100H to link properly. Maybe I really must learn new assembler syntax and switch to newer assembler..

But right now, I don't use UFD as boot device again. I though it will be easier if I'm using UFD. Now, I'm using one of my harddisk partitions to test my "hello world" OS. And the boot code run properly.. And I'm confused again.. I'm using Visual C++ 2005 to generate the code, and I don't know what should I do.. (when I'm using DOS EXE, I just extract the code starting from 7E00H).. But in PE format, there are RVA, sections, and a lot.. Is it possible to use Visual C++? Or I must download GCC and DD (I live in slow internet connection country)?

Posted: Thu Jul 05, 2007 10:27 am
by hailstorm
I would suggest you get gcc somehow (maybe you have a friend who has broadband?). Using gcc you can create executables with coff header format. Though I know PE and coff aren't that much different from eachother, coff is much better explained I guess.
I also think it is possible to generate MZ executables using VC++ 2005, but you have to dig into your project's options...

About tlink; I guess you could use org 100h, tlink should relocate all references to variables automatically, that is, adding 100h to references.

Good luck!

Posted: Fri Jul 06, 2007 6:49 am
by SolidSnake
Thanks for the suggesting..

I still don't understand about the use of PE or COFF here.. I have write boot code in sector 0 of partition, and the code will read 6 sector starting at sector 1 to memory 0000:8000H. And then, I jump far using RETF to 0000:8000H. What should I do next?

It's that I should put my kernel code starting at sector 2? But when I'm using Visual C++ and generating PE EXE, I don't know if I could just put the ".TEXT" section and ".DATA" section into sector 2. What happen if I use COFF?

Posted: Fri Jul 06, 2007 11:33 am
by hailstorm
The reason for these headers in executables is for the kernel to know where the text, data, bss and other sections can be found. Also symbol and relocation data can be found in these headers. That's also the reason why it is hard to understand how to read the header of an executable.

Althought I bet it is possible, it is hard to code logic in a bootsector that reads an executable and that examines the header where it should load the sections in memory. Therefore OS developers program a second stage bootloader which is somewhat bigger in size, but also can do a little more.

My suggestion is that you try to program a bootsector that supports fat. So you can load a secondstage bootloader that does the rest. There is enough information to be found on these subjects, but it is somewhat hard to grasp...

I wish you luck.

Posted: Sat Jul 07, 2007 6:28 am
by SolidSnake
Thanks.. I understand now... It seems that boot loader do something like program loader.. So, maybe I can program the kernel in PE format, and then load the PE file into memory according the BaseMemory field, and then jump into InitialProgramEntry, I hope that will work..
Thanks again..

Posted: Sat Jul 07, 2007 8:18 am
by XCHG
Here are some food for thought:

• BIOS does NOT load the MBR into 0x0000:0x7C0, it loads it into 0x0000:0x7C00. Note the extra zero to the right of the latter number. The former is 1984 in decimal but the latter is 31744.

• Your best bet for coding a bootstrap is to use NASM that is freely available in the Internet.

• When using NASM, assemble your bootstrap into a flat binary file using the "-f bin" switch.

Posted: Sat Jul 07, 2007 8:19 am
by Dex
You could assemble it as a mz EXE and load it with bootprog, a boot load that can load mz exe or com files: http://alexfru.chat.ru/epm.html#bootprog

Posted: Mon Jul 09, 2007 6:27 am
by SolidSnake
Thanks for the link, I'm downloading the resources from there right now.. It should give me more information about OS implementation..

And thanks, XCHG for the food.. I'll try NASM too..

I've tried to call the PE code after my boot sector code, but I just realized some code in the PE file use something like 32-bit CALL (intrasegment call, but not with 2 bytes displacement, but 4 bytes displacement).. I think in real mode, the CPU will just use the 2 first bytes. It seems that I must switch to protected mode first before calling the PE file, and still doing a lot in assembler rather in C. Maybe that's what GRUB doing in the os tutorial I read (I can't follow the tutorial coz I don't have GRUB, so I decide to write the bootcode myself, but I realize it's too hard).