Hello and thanks for viewing this,

I have been working on assembly now for a few weeks during my free time, and I thought it would be interesting to learn a small bit before.  Using ideas that I had found by reading other people's code and various tutorials, I started to work on a very Basic Bootsector who's single purpose is to print a string, and then halt the processor.

I have been having a few problems, the PC / Emulator will boot up, but then just hang.  I have posted the code here (for use with Netwide Assembler) and would appreciate any help from the experts.




;XIX System 19 BootSector - Version pre-Alpha
;this will eventually be able to boot the kernel of XIX
;some time in the future, implement the ability to boot
;multiple systems

;assembler directive for 32-bit code
;assembler directive to set origin to 0x7C00

;main function for booting up the bootsector
boot:
mov , dl ;save the boot drive number to bootdrv, (0x00 = floppy)

mov ax, cs ;setup the ds register indirectly
mov ds, ax
mov es, ax
mov fs, ax

mov ax, 0x1D0 ;setup stack at 0x1D0
mov ss, ax ;set StackSegment Register to 0x1D0
mov sp, 0x200 ;set StackPointer to denote 512 byte stack

mov ax, 0xb800 ;setup video segment
mov gs, ax

mov si, sysmess ;load the system startup message into StringIndex

call prnt ;call the prntset function

hlt ;REMOVE AFTER TEST


;sub-function for printing the loaded string
prnt:
mov ah, 0x0E ;load teletype character (we want to print something)
mov bh, 0x00 ;tell to print on page 1
mov bl, 0x07 ;black background, white text, non-flashing

.nextchar ;label to jump to for repeating until finished
lodsb ;loads SI into AL for printing
or al, al ;set zero flag if AL = nullchar '0' (set at end of message)

jz .end ;if zero flag set, go to end of sub-function

int 0x10 ;run BIOS video interrupt to prin message
jmp .nextchar ;jump and repeat

.end
ret


;variables for data and strings
bootdrv db 0 ;will be set to the boot drive number (hopefully 0x00)

sysmess db 'XIX System 19 BootSector - Version pre-Alpha',13,10,0 ;string to print
;13 - character return
;10 - new line
;0 - null character


;appendages for bootloader
times 510-($-$$) db 0 ;fill unused space upto 510 bytes with 0
signature dw 0xAA55 ;set bootloader signature

Posted on 2009-09-11 12:21:18 by XeonX369

The problem is :

  mov si, sysmess      ;load the system startup message into StringIndex

That translates to :

  mov si, WORD PTR

The solution is :

 lea si, sysmess         ;load the Address of the system startup message into si register

Or :

 mov si,offset sysmess ;load the program offset of the ...

Posted on 2009-09-11 12:28:52 by Homer
Hello Homer, thank you for helping me.

Unfortunately I have tried to replace the problem with:

lea si, sysmess

But when I attempt to assembly it in NASM, it gives the following error:

./Source/bootsector.asm:25: error: invalid combination of opcode and operands

So, I suppose that I am still in need of help, apparently NASM doesn't like the solution.

I would really appreciate your continued help.
Posted on 2009-09-11 12:41:45 by XeonX369
A guess? because it is a forwards reference.
You could avoid that : need to declare the data before you reference its label.

boot: jmp ahead
SysMess db 'String Here',0
ahead: mov , dl

Most assemblers don't like forwards references - also true of a lot of other compilers / languages.
There's ALWAYS ways around problems like this.
Another way to do this would be to use 'pc-relative coding'.

Posted on 2009-09-11 12:56:24 by Homer
I will try that when I can,

it does sound rather logical to me.

Thanks for the help
Posted on 2009-09-11 13:23:10 by XeonX369
use instead of
Posted on 2009-09-11 19:09:13 by lone_samurai5

The problem is :
  mov si, sysmess      ;load the system startup message into StringIndex

That translates to :
  mov si, WORD PTR

The solution is :
  lea si, sysmess        ;load the Address of the system startup message into si register

Or :
  mov si,offset sysmess ;load the program offset of the ...


Erm, that is incorrect. Unlike MASM, NASM references the address/offset of a label by default unless explicitly told to operate on a memory value via square brackets. This helps reduce ambiguity when looking at any given line of code.

Also, If he were to utilize LEA, it would need to be "lea si,", hence the specified error. As for why LEA needs square brackets in NASM, my best guess is to indicate that complex effective address calculations are valid for the instruction... consistency, if you will.



A guess? because it is a forwards reference.
You could avoid that : need to declare the data before you reference its label.

boot: jmp ahead
SysMess db 'String Here',0
ahead: mov , dl

Most assemblers don't like forwards references - also true of a lot of other compilers / languages.
There's ALWAYS ways around problems like this.
Another way to do this would be to use 'pc-relative coding'.


This is logical, but also incorrect. NASM, being a two-pass assembler, doesn't have any issues referencing forward labels. Declarations/definitions only become necessary within the preprocessor phase.


use instead of


That hits the nail on the head. is prefixing 16-bit instructions with 0x66/0x67 operand/address override opcodes. When the processor, running in 16-bit Real Mode, gets to these instructions, it is interpreting them as overrides to perform 32-bit instructions. When this happens, you can roll the dice as to how the computer is going to ultimately respond... hedge your bets on it simply hanging, or even resetting due to a triple-fault.

Also, HLT at the end of your boot code should be followed by a hanging jump mechanism, unless you have explicitly disabled interrupts, as so:


.halt:
hlt
jmp .halt

;OR

cli
hlt
Posted on 2009-09-12 13:33:23 by SpooK
Thanks to all who helped me overcome this minor issue.

I never thought about the being an issue.  I thought that because produced 16-bit code, 32 would be alright in RealMode.  Now it all makes sense because I remember Real Mode is in 16 bit.

Thanks Again,

Xeon
Posted on 2009-09-14 09:38:25 by XeonX369