NASM's "ORG", Stack and Segment Registers in Real Mode

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
Haroogan
Member
Member
Posts: 28
Joined: Thu Aug 04, 2011 1:10 pm

NASM's "ORG", Stack and Segment Registers in Real Mode

Post by Haroogan »

First of all, I would like to show the code, which works fine:

Stage 1 Boot:

Code: Select all

;0x00000000 - 0x000003FF - Real Mode Interrupt Vector Table
;0x00000400 - 0x000004FF - BIOS Data Area
;0x00000500 - 0x00007BFF - Unused
;0x00007C00 - 0x00007DFF - Stage 1 Boot
;0x00007E00 - 0x0009FFFF - Unused <----- I will load Stage 2 Boot here, since this is free memory space :D
;0x000A0000 - 0x000BFFFF - Video RAM (VRAM) Memory
;0x000B0000 - 0x000B7777 - Monochrome Video Memory
;0x000B8000 - 0x000BFFFF - Color Video Memory
;0x000C0000 - 0x000C7FFF - Video ROM BIOS
;0x000C8000 - 0x000EFFFF - BIOS Shadow Area
;0x000F0000 - 0x000FFFFF - System BIOS

BITS 16
ORG 0x7C00

JMP main

%include "Utility.inc"

message1 DB "Stage 1 Boot",13,10,0
message2 DB "FAIL",13,10,0

diskAddressPacket:
	size			DB 16
	reserved 		DB 0
	numberOfSectors DW 1
	bufferOffset 	DW 0x7E00
	bufferSegment 	DW 0
	startSector 	DQ 1

main:
	XOR AX,AX
	MOV DS,AX
	MOV SI,message1
	
	CALL String.print
	
	.reset:
	XOR AH,AH
	INT 0x13
	JC .reset
	
	MOV AH,0x42
	;BIOS has already put drive index to DL register.
	MOV SI,diskAddressPacket
	
	INT 0x13
	
	JC .exit
	
	JMP 0:0x7E00
	
	.exit:
	
	MOV SI,message2
	
	CALL String.print
	
	JMP $
	
TIMES 510 - ($ - $$) DB 0

DW 0xAA55 ;Boot Signature
By the way in the beginning - it's a memory map for Real Mode. I use it just as a quick reference :D.

Stage 2 Boot:

Code: Select all

BITS 16
ORG 0x7E00

JMP main

%include "Utility.inc"

message1 DB "Stage 2 Boot",13,10,0

main:
	XOR AX,AX
	MOV DS,AX
	MOV SI,message1
	
	CALL String.print
	
	JMP $
Image

Questions:

1. So AFAIK ORG directive is used to tell the compiler which offset to use for variables. In other words, now:

MOV SI,message1 = MOV SI,0x7C00+(some offset which was computed at the compile time)

Am I right about it?

2. What is going to happen if I will remove ORG directive at all? Will I have to utilize Segment Registers then? How would I reference variables then? (Just assume the case when you don't know where is your program)

3. What about Segment Registers in general? Do I have to set em up or just ignore, in case of Real Mode boot loader? (The DS was set up in this example just for string output... you have probably got it already)

4. And what about stack? Where is stack? I didn't specify anything about it in the program. Does BIOS setup SS and SP registers with some specific values after finding my boot loader?

5. Some additional information from debugging, because I'm a bit confused about it:

Image
Bietje
Member
Member
Posts: 100
Joined: Wed Apr 20, 2011 6:57 am

Re: NASM's "ORG", Stack and Segment Registers in Real Mode

Post by Bietje »

Haroogan wrote: Questions:

1. So AFAIK ORG directive is used to tell the compiler which offset to use for variables. In other words, now:

MOV SI,message1 = MOV SI,0x7C00+(some offset which was computed at the compile time)

Am I right about it?

2. What is going to happen if I will remove ORG directive at all? Will I have to utilize Segment Registers then? How would I reference variables then? (Just assume the case when you don't know where is your program)

3. What about Segment Registers in general? Do I have to set em up or just ignore, in case of Real Mode boot loader? (The DS was set up in this example just for string output... you have probably got it already)

4. And what about stack? Where is stack? I didn't specify anything about it in the program. Does BIOS setup SS and SP registers with some specific values after finding my boot loader?
1. correct

2. Yes you will have to utilize the segment registers then. You can also let nasm spit out 32 bit elf object files and use a linker to specify the load address.

3. just ignore them isn't very smart. The only thing you do know for sure is that the bios will load you at the linear address 0x7c00, but since intel works with a segmented model are there several ways to address linear address 0x7c00. By setting the segment to 0x7c0 and the offset to 0 or by setting the segment to 0 and the offset to 0x7c00.
Now you may wonder why I tell you this, well some bioses load you in at 0x0:0x7c00 (almost every bios) and all other bioses at 0x7c0:0x0. So you might what to flush you code segment too.

Code: Select all

	cli
; we do not want timer irq's and crap like that
	jmp 0x0:.flush
; 	there are creepy bioses which load you in at 0x7c0:0x0
.flush:
	xor ax, ax
	mov ds, ax

	mov es, ax	; general and extra segmets
	mov gs, ax
	mov fs, ax

	mov ss, ax	; stack segment
	mov sp, OL_LOADOFF
	mov bp, sp
	sti
That brings me to your fourth question.. the stack is where you told it to be. If you do not tell it where the stack pointer should be in memory, then you do not know. As far as I know, is the stack not at a default location after you are loaded by the bios. So I suggest you setup a stack too as soon as you are loaded in. A very common 'real mode stack pointer' is pointed to 0x7c00.

5. What bochs is doing there, is nothing more then spewing values of your registers.
Haroogan
Member
Member
Posts: 28
Joined: Thu Aug 04, 2011 1:10 pm

Re: NASM's "ORG", Stack and Segment Registers in Real Mode

Post by Haroogan »

1. A. What if:

Code: Select all

ORG 0xFFFF
Then

MOV SI,var = MOV SI,0xFFFF+(offset to var > 0)

So... SI obviously is unable to accommodate this number. What's gonna happen? Solution?

1. B. By the way, "ORG X" specifies offset (e. g. X) as a physical address? (I mean there is no mess with segments and etc. right?)

3. So you recommend me to zero them all?
5. Yeah I know that it is spewing values. I just wanted to emphasize that all segment registers are already zeroed somehow without my help. Why is that? So the stack seems to be wrapping from 0:0 to 0:FFF4, isn't it?

I guess my Q's sound a bit weird, but I just want clear things up right before I start some serious programming. Thanks man!
egos
Member
Member
Posts: 612
Joined: Fri Nov 16, 2007 1:59 pm

Re: NASM's "ORG", Stack and Segment Registers in Real Mode

Post by egos »

Haroogan wrote:Then

MOV SI,var = MOV SI,0xFFFF+(offset to var > 0)

So... SI obviously is unable to accommodate this number. What's gonna happen? Solution?
Smart compiler will generate an error in this case. Moreover it must generate an error for e.g. mov ax,[0xFFFF] too. But most of modern 32/64-bit compilers don't care about this small stuff. Therefore it is need to do something like "if $>0x10000 then error" at the end of segment. For example, in fasm I do this:

Code: Select all

virtual
rb 10000h-$ ; it will generate an error if $>10000h
end virtual
1. B. By the way, "ORG X" specifies offset (e. g. X) as a physical address? (I mean there is no mess with segments and etc. right?)
"ORG X" specifies starting offset inside any segment. It will specify a physical address only if base address of the segment is zero.
3. So you recommend me to zero them all?
It is convenient if your code is placed entirely in first 64 kb of physical memory. You have no need to reset cs if you don't use ip obviously. You have no need to set es to zero if you use it as a "base" for reading (7E0h, 800h, 820h and so on) but you can do it if you want to reset it only on 64 kb boundaries (0!, 1000(0)h, 2000(0)h and so on). You can forget about fs and gs in RM at all.
5. Yeah I know that it is spewing values. I just wanted to emphasize that all segment registers are already zeroed somehow without my help. Why is that? So the stack seems to be wrapping from 0:0 to 0:FFF4, isn't it?
If you want be sure in it you should make it by yourself! Look at any well bootloader and you will understand it. Here is from mine:

Code: Select all

  org 7C00h

  xor ax,ax
  cli
  mov ss,ax
  mov sp,$$
  sti
  jmp 0:@f ; it needs for me only for putstr routine
@@:
  mov ds,ax
  call putstr
  db 13,10,"Message...",32,0
  ...
putstr:
  pop si
  ...
  jmp si ; or push si/ret
If you have seen bad English in my words, tell me what's wrong, please.
Haroogan
Member
Member
Posts: 28
Joined: Thu Aug 04, 2011 1:10 pm

Re: NASM's "ORG", Stack and Segment Registers in Real Mode

Post by Haroogan »

Awesome, Thank you!
Post Reply