How can I fix my segment regsiters.
-
- Posts: 9
- Joined: Sat Sep 29, 2007 8:45 am
How can I fix my segment regsiters.
How would i fix my segment registers?
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.
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.
-
- Posts: 9
- Joined: Sat Sep 29, 2007 8:45 am
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
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
normally, you would begin your bootsector with an org statement like:
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:
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)
Code: Select all
org 0x7C00
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:
...
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)
-
- Posts: 9
- Joined: Sat Sep 29, 2007 8:45 am
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.
Thank you in advanced, I wish to learn.
-
- Posts: 9
- Joined: Sat Sep 29, 2007 8:45 am
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
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.
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.
-
- Posts: 9
- Joined: Sat Sep 29, 2007 8:45 am
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
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 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
- Combuster
- 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:
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.