How can I fix my segment regsiters.

Programming, for all ages and all languages.
Post Reply
TsrChristopher
Posts: 9
Joined: Sat Sep 29, 2007 8:45 am

How can I fix my segment regsiters.

Post by TsrChristopher »

How would i fix my segment registers?
User avatar
bluecode
Member
Member
Posts: 202
Joined: Wed Nov 17, 2004 12:00 am
Location: Germany
Contact:

Post by bluecode »

First of all you should read How to ask Questions the smart way. I know that you opened another thread but not everyone visiting this board will know. They won't understand what you are talking about (because you do not provide any context).

Then find out how you adress memory in real mode (tip: segment and offset). This will also tell you what segment registers are and how you are supposed to use them. After that read about the boot process. This will tell you where you are in memory after your bootsector got loaded off the floppy/harddisk (You need to know where something is in order to address it, right?). I think then you will find the solution yourself.
TsrChristopher
Posts: 9
Joined: Sat Sep 29, 2007 8:45 am

Post by TsrChristopher »

So I took your advice, but yet I am still confused, I have read about memory management and how to convert decimal to hex and binary which I am shoked I understood.

The Boot Sector is loaded in 0x7C00 and is 512 bytes long. So does that mean I should point to 8624? And If so, may I ask exactly how to point to that in NASM do I do [ORG 8624]

Thank you
User avatar
JAAman
Member
Member
Posts: 879
Joined: Wed Oct 27, 2004 11:00 pm
Location: WA

Post by JAAman »

normally, you would begin your bootsector with an org statement like:

Code: Select all

org 0x7C00
of course it depends on what asembler you are using... that example should work with nasm, but others might be different

but that isnt completely correct either

the org statement tells the assembler, that your file starts at that address, rather than starting at address 0 (org 0 is default usually), but that address is an offset from the segment base -- meaning it depends on your segment

in RMode (that is real mode) your segment base is always 16*segment number -- so in order to use org, you need to know what your segments are -- and that will be different on every computer...

the best way to solve this is to adjust your segment bases at startup -- for example:

Code: Select all

bits 16
org 0x7C00

jmp short init:                    ;clear BPB -- needed only if you implement the BPB -- required for FAT compliant disks
nop

                   ; insert BPB here
init:
xor AX, AX                        ; this line puts 0 into AX...
mov DS, AX                      ; then this line puts the 0 into DS
mov ES, AX                       ; and ES
mov SS, AX                      ; and SS
mov SP, top_of_stack        ; you must always put the stack somewhere...

jmp 0:start                       ;this line is only needed if you use absolute addressing
start:
...
this is only an example:
the key is, the address of start isnt defined -- only the absolute address, so there is no way of knowing what is in any of the segment registers on startup -- the only register you can count on is DL should contain the bootdrive (although that isnt necessarily going to be completely acurate...)

the first lines (before and including the BPB) are only necessary for FAT12/16/32 disks (other disks might have other requirements though...), but basically, you need to make sure you know what is in your segment registers before you use them -- if you use org 0x7C00 then you will need to load 0 into at least DS (the others dont need to be loaded until you use them) if you use org 0 (or dont have an org statement) then you will need to load 0x7C0 into DS (0x7C0*16=0x7C00 -- starting position is at address 0) this is not used as often, as it makes accessing the information at the beginning of memory more difficult to access

you also need to be sure you load something into SS:SP (the stack pointer), so that any stack usages go somewhere sane -- you have no way of knowing where the stack is on startup, or how much memory it can safely use...)

as for the last jmp (a far jump) it must be used before any absolute jumps (which can be avoided within the bootsector, but be careful) because you dont know what segment:offset is being used (the assembler will assume CS==DS), so you dont know what the offset is, so if you jump to a segment offset, you must know where that will land, which you cannot know until you set CS (if your careful, this can be avoided within the bootsector, then you use a far jump when jumping to your next section of code)
TsrChristopher
Posts: 9
Joined: Sat Sep 29, 2007 8:45 am

Post by TsrChristopher »

I appreciate your responce, now the documents that I read explained nothing like what you are telling me, could you please direct me of a more usful document or tutorial. Now, I have tried google and I must say I cannot find anything usefull so I probably lack the search capabilities.

Thank you in advanced, I wish to learn.
TsrChristopher
Posts: 9
Joined: Sat Sep 29, 2007 8:45 am

Post by TsrChristopher »

I hope you can help with the code I have, here it is.

Code: Select all

[ORG 0x7C00]
[BITS 16]

main:
	mov ax, 0x0000 		;chance the graphics display
	mov al, 11h
	int 0x10

	cli
	mov ds, ax
	mov es, ax
	mov fs, ax
	mov gs, ax

	mov ax, 0x0000
	mov ss, ax
	mov sp, 0xFFFF	

	mov si, welcome
	call PrintString

	jmp $

PrintString:
	lodsb
	or al, al
	jz .DONE
	mov ah, 0x0E
	mov bh, 0x00
	mov bl, 0x07
	int 0x10
	jmp PrintString
.DONE
	ret

welcome db "[Welcome]",0x0d,0x0a,0x00 
frank
Member
Member
Posts: 729
Joined: Sat Dec 30, 2006 2:31 pm
Location: East Coast, USA

Post by frank »

Try putting mov ax, 0 in between cli and mov ds, ax. Also try reading some tutorials on assembly.

http://www.geocities.com/siliconvalley/ ... les01.html
http://www.xs4all.nl/~smit/asm01001.htm
http://www.csn.ul.ie/~darkstar/assembler/

Here take a look at a few of those and see if that helps to clear up anything.
TsrChristopher
Posts: 9
Joined: Sat Sep 29, 2007 8:45 am

Post by TsrChristopher »

frank I have noticed that my bootloader also was not handing over control to my actual kernel, i don't know why, but here is my bootloader.

Code: Select all

;*************************************************************************
[BITS 16]
ORG 0
jmp     START

OEM_ID                db "QUASI-OS"
BytesPerSector        dw 0x0200
SectorsPerCluster     db 0x01
ReservedSectors       dw 0x0001
TotalFATs             db 0x02
MaxRootEntries        dw 0x00E0
TotalSectorsSmall     dw 0x0B40
MediaDescriptor       db 0xF0
SectorsPerFAT         dw 0x0009
SectorsPerTrack       dw 0x0012
NumHeads              dw 0x0002
HiddenSectors         dd 0x00000000
TotalSectorsLarge     dd 0x00000000
DriveNumber           db 0x00
Flags                 db 0x00
Signature             db 0x29
VolumeID              dd 0xFFFFFFFF
VolumeLabel           db "FIXANYWHERE"
SystemID              db "FAT12   "

START:
; code located at 0000:7C00, adjust segment registers
     cli
     mov     ax, 0x07C0
     mov     ds, ax
     mov     es, ax
     mov     fs, ax
     mov     gs, ax
; create stack
     mov     ax, 0x0000
     mov     ss, ax
     mov     sp, 0xFFFF
     sti
; post message
     mov     si, msgLoading
     call    DisplayMessage
LOAD_ROOT:
; compute size of root directory and store in "cx"
     xor     cx, cx
     xor     dx, dx
     mov     ax, 0x0020                          ; 32 byte directory entry
     mul     WORD [MaxRootEntries]               ; total size of directory
     div     WORD [BytesPerSector]               ; sectors used by directory
     xchg    ax, cx
; compute location of root directory and store in "ax"
     mov     al, BYTE [TotalFATs]                ; number of FATs
     mul     WORD [SectorsPerFAT]                ; sectors used by FATs
     add     ax, WORD [ReservedSectors]          ; adjust for bootsector
     mov     WORD [datasector], ax               ; base of root directory
     add     WORD [datasector], cx
; read root directory into memory (7C00:0200)
     mov     bx, 0x0200                          ; copy root dir above bootcode
     call    ReadSectors
; browse root directory for binary image
     mov     cx, WORD [MaxRootEntries]           ; load loop counter
     mov     di, 0x0200                          ; locate first root entry
.LOOP:
     push    cx
     mov     cx, 0x000B                          ; eleven character name
     mov     si, ImageName                       ; image name to find
     push    di
rep  cmpsb                                       ; test for entry match
     pop     di
     je      LOAD_FAT
     pop     cx
     add     di, 0x0020                          ; queue 

     loop    .LOOP
     jmp     FAILURE
LOAD_FAT:
; save starting cluster of boot image
     mov     si, msgCRLF
     call    DisplayMessage
     mov     dx, WORD [di + 0x001A]
     mov     WORD [cluster], dx                  ; file's first cluster
; compute size of FAT and store in "cx"
     xor     ax, ax
     mov     al, BYTE [TotalFATs]                ; number of FATs
     mul     WORD [SectorsPerFAT]                ; sectors used by FATs
     mov     cx, ax
; compute location of FAT and store in "ax"
     mov     ax, WORD [ReservedSectors]          ; adjust for bootsector
; read FAT into memory (7C00:0200)
     mov     bx, 0x0200                          ; copy FAT above bootcode
     call    ReadSectors
; read image file into memory (0050:0000)
     mov     si, msgCRLF
     call    DisplayMessage
     mov     ax, 0x0050
     mov     es, ax                              ; destination for image
     mov     bx, 0x0000                          ; destination for image
     push    bx
LOAD_IMAGE:
     mov     ax, WORD [cluster]                  ; cluster to read
     pop     bx                                  ; buffer to read into
     call    ClusterLBA                          ; convert cluster to LBA
     xor     cx, cx
     mov     cl, BYTE [SectorsPerCluster]        ; sectors to read
     call    ReadSectors
     push    bx
; compute next cluster
     mov     ax, WORD [cluster]                  ; identify current cluster
     mov     cx, ax                              ; copy current cluster
     mov     dx, ax                              ; copy current cluster
     shr     dx, 0x0001                          ; divide by two
     add     cx, dx                              ; sum for (3/2)
     mov     bx, 0x0200                          ; location of FAT in memory
     add     bx, cx                              ; index into FAT
     mov     dx, WORD [bx]                       ; read two bytes from FAT
     test    ax, 0x0001
     jnz     .ODD_CLUSTER
.EVEN_CLUSTER:
     and     dx, 0000111111111111b               ; take low twelve bits
    jmp     .DONE
.ODD_CLUSTER:
     shr     dx, 0x0004                          ; take high twelve bits
.DONE:
     mov     WORD [cluster], dx                  ; store new cluster
     cmp     dx, 0x0FF0                          ; test for end of file
     jb      LOAD_IMAGE
DONE:
     mov     si, msgCRLF
     call    DisplayMessage
     push    WORD 0x0050
     push    WORD 0x0000
     retf
FAILURE:
     mov     si, msgFailure
     call    DisplayMessage
     mov     ah, 0x00
     int     0x16                                ; await keypress
     int     0x19                                ; warm boot computer

;*************************************************************************
; PROCEDURE DisplayMessage
; display ASCIIZ string at "ds:si" via BIOS
;*************************************************************************
DisplayMessage:
     lodsb                                       ; load next character
     or      al, al                              ; test for NUL character
     jz      .DONE
     mov     ah, 0x0E                            ; BIOS teletype
     mov     bh, 0x00                            ; display page 0
     mov     bl, 0x07                            ; text attribute
     int     0x10                                ; invoke BIOS
     jmp     DisplayMessage
.DONE:
     ret

;*************************************************************************
; PROCEDURE ReadSectors
; reads "cx" sectors from disk starting at "ax" into memory location "es:bx"
;*************************************************************************
ReadSectors:
.MAIN
     mov     di, 0x0005                          ; five retries for error
.SECTORLOOP
     push    ax
     push    bx
     push    cx
     call    LBACHS
     mov     ah, 0x02                            ; BIOS read sector
     mov     al, 0x01                            ; read one sector
     mov     ch, BYTE [absoluteTrack]            ; track
     mov     cl, BYTE [absoluteSector]           ; sector
     mov     dh, BYTE [absoluteHead]             ; head
     mov     dl, BYTE [DriveNumber]              ; drive
     int     0x13                                ; invoke BIOS
     jnc     .SUCCESS                            ; test for read error
     xor     ax, ax                              ; BIOS reset disk
     int     0x13                                ; invoke BIOS
     dec     di                                  ; decrement error counter
     pop     cx
     pop     bx
     pop     ax
     jnz     .SECTORLOOP                         ; attempt to read again
     int     0x18
.SUCCESS
     mov     si, msgProgress
     call    DisplayMessage
     pop     cx
     pop     bx
     pop     ax
     add     bx, WORD [BytesPerSector]           ; queue next buffer
     inc     ax                                  ; queue next sector
     loop    .MAIN                               ; read next sector
     ret

;*************************************************************************
; PROCEDURE ClusterLBA
; convert FAT cluster into LBA addressing scheme
; LBA = (cluster - 2) * sectors per cluster
;*************************************************************************
ClusterLBA:
     sub     ax, 0x0002                          ; zero base cluster number
     xor     cx, cx
     mov     cl, BYTE [SectorsPerCluster]        ; convert byte to word
     mul     cx
     add     ax, WORD [datasector]               ; base data sector
     ret

;*************************************************************************
; PROCEDURE LBACHS
; convert "ax2; LBA addressing scheme to CHS addressing scheme
; absolute sector = (logical sector / sectors per track) + 1
; absolute head   = (logical sector / sectors per track) MOD number of heads
; absolute track  = logical sector / (sectors per track * number of heads)
;*************************************************************************
LBACHS:
     xor     dx, dx                              ; prepare dx:ax for operation
     div     WORD [SectorsPerTrack]              ; calculate
     inc     dl                                  ; adjust for sector 0
     mov     BYTE [absoluteSector], dl
     xor     dx, dx                              ; prepare dx:ax for operation
     div     WORD [NumHeads]                     ; calculate
     mov     BYTE [absoluteHead], dl
     mov     BYTE [absoluteTrack], al
     ret

absoluteSector db 0x00
absoluteHead   db 0x00
absoluteTrack  db 0x00

datasector  dw 0x0000
cluster     dw 0x0000
ImageName   db "LOADER  BIN"
msgLoading  db 0x0D, 0x0A, "Loading Boot Image ", 0x0D, 0x0A, 0x00
msgCRLF     db 0x0D, 0x0A, 0x00
msgProgress db ".", 0x00
msgFailure  db 0x0D, 0x0A, "ERROR : Press Any Key to Reboot", 0x00

     TIMES 1474558-($-$$) DB 0
     DW 0xAA55
Tyler
Member
Member
Posts: 514
Joined: Tue Nov 07, 2006 7:37 am
Location: York, England

Post by Tyler »

TsrChristopher wrote:frank I have noticed that my bootloader also was not handing over control to my actual kernel, i don't know why, but here is my bootloader.

Code: Select all

DONE:
     mov     si, msgCRLF
     call    DisplayMessage
     push    WORD 0x0050
     push    WORD 0x0000
     retf
That is where "your" Bootloader calls the kernel. It pushes the location onto the stack and perfroms a long return which pops those values into CS and IP. The Kernel was of course loaded at this location earlier in the code.
TsrChristopher
Posts: 9
Joined: Sat Sep 29, 2007 8:45 am

Post by TsrChristopher »

So the bootstrap is always running?
Tyler
Member
Member
Posts: 514
Joined: Tue Nov 07, 2006 7:37 am
Location: York, England

Post by Tyler »

*Leaves to go help people who are actually ready to develop an OS*
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Post by Combuster »

Given your line of questioning you didn't do the required reading (nor that other thing we told you to read twice). See for yourself if you can live up to that or consider practicing your skills somewhere else.
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
Post Reply