flat assembler
Message board for the users of flat assembler.

Index > OS Construction > Help to understand GDT and use of CS and DS

Author
Thread Post new topic Reply to topic
Fulgurance



Joined: 27 Nov 2017
Posts: 276
Fulgurance 15 Sep 2018, 16:33
Hello, in previous post, i have asked many questions, but i'm sorry, i don't understand all.

I don't understand 2 problems:

First, i don't understand structure of segment descriptor on GDT, for Code and Data. On this example, i don't understand what is base and limit in descriptor: http://a.michelizza.free.fr/pmwiki.php?n=TutoOS.ProtectedMode

What is 0xFF in this line:
Code:
db 0xFF, 0xFF, 0x0, 0x0, 0x0, 10011011b, 11011111b, 0x0    

And why ds and es at start of this example are set with the same value ? Code don't start at the same adress ? (i don't understand)

In second, i don't understand very well what is CS and DS register. For me, CS and DS is for ask processor where is next code and data segments are used. But i don't understand what's happening when i add value on DS for example for processor.
Post 15 Sep 2018, 16:33
View user's profile Send private message Reply with quote
DimonSoft



Joined: 03 Mar 2010
Posts: 1228
Location: Belarus
DimonSoft 15 Sep 2018, 22:54
Base is a place in linear addressing space where the segment starts, limit is the size of the segment. 0xFF’s (as well as lower nibble of the 7th byte) specify the largest possible value for the limit, i.e. 0xFFFFF which, combined with Granularity flag set to 1, means that offsets in the segment will range from 0 to 0xFFFFFFFF.

DS and ES are presumably set to the same value since certain pieces of code might later use instructions that implicitly use ES register to look for memory operands. The most noticeable ones are string-handling instructions. Another reason is that some BIOS functions use ES to pass segment number as a parameter. I haven’t looked into their UTILS.INC file, so I’m just speculating on that. In fact, they could be set to the same value even if there’s no instruction/function requiring this, just for the purpose of having well-defined values in segment registers.

Every byte out there can have a lot of different logical addresses while being only in one place physically. Even though code and data are placed close to each other it may still be more practical to address them separately. Although I personally prefer to have well-defined value in my CS within bootloader and have this value equal in all the segment registers.

CS and DS are registers which are used to store part of full logical address. In real mode their values are used as addends (after multiplying by 16), in protected mode a more complex scheme is used, as described in the tutorial you’ve linked, namely the register value contains an index to a descriptor table where the actual addend value is stored.
Post 15 Sep 2018, 22:54
View user's profile Send private message Visit poster's website Reply with quote
Fulgurance



Joined: 27 Nov 2017
Posts: 276
Fulgurance 23 Sep 2018, 23:40
Hummm ... okay.
I have made this to test use of segments register and how to switch to protected mode, but i don't found why this code crash (i use only first sector, but this code don't work)
Code:
use16
org 0x0

mov ax,0x7C0
mov ds,ax
mov es,ax
mov fs,ax
mov gs,ax

cli
lgdt [GDT32Descriptor]
mov eax,cr0
or al,0x1
mov cr0,eax
jmp SetupProtectedMode

SetupProtectedMode:
mov ax,0x10
mov ds,ax
mov es,ax
mov fs,ax
mov gs,ax
jmp dword 0x8:StartProtectedMode

use32
StartProtectedMode:
mov byte [0xB8000],'A'
Main32:
jmp short Main32

use16
GDT32:
.NullDescriptor:
    db 0, 0, 0, 0, 0, 0, 0, 0
.CodeDescriptor:
    db 0xFF, 0xFF, 0x0, 0x0, 0x0, 10011011b, 11011111b, 0x0
.DataDescriptor:
    db 0xFF, 0xFF, 0x0, 0x0, 0x0, 10010011b, 11011111b, 0x0
.End:
GDT32Descriptor:
.Limit:
dw GDT32.End - GDT32 - 1
.Base:
dd GDT32

db 510-($-$$) dup 0x90
dw 0xAA55    
Post 23 Sep 2018, 23:40
View user's profile Send private message Reply with quote
DimonSoft



Joined: 03 Mar 2010
Posts: 1228
Location: Belarus
DimonSoft 24 Sep 2018, 11:17
Fulgurance wrote:
Hummm ... okay.
I have made this to test use of segments register and how to switch to protected mode, but i don't found why this code crash (i use only first sector, but this code don't work)
Code:
use16
org 0x0

mov ax,0x7C0
mov ds,ax
mov es,ax
mov fs,ax
mov gs,ax

cli
lgdt [GDT32Descriptor]
mov eax,cr0
or al,0x1
mov cr0,eax
jmp SetupProtectedMode

SetupProtectedMode:
mov ax,0x10
mov ds,ax
mov es,ax
mov fs,ax
mov gs,ax
jmp dword 0x8:StartProtectedMode

use32
StartProtectedMode:
mov byte [0xB8000],'A'
Main32:
jmp short Main32

use16
GDT32:
.NullDescriptor:
    db 0, 0, 0, 0, 0, 0, 0, 0
.CodeDescriptor:
    db 0xFF, 0xFF, 0x0, 0x0, 0x0, 10011011b, 11011111b, 0x0
.DataDescriptor:
    db 0xFF, 0xFF, 0x0, 0x0, 0x0, 10010011b, 11011111b, 0x0
.End:
GDT32Descriptor:
.Limit:
dw GDT32.End - GDT32 - 1
.Base:
dd GDT32

db 510-($-$$) dup 0x90
dw 0xAA55    

Haven’t run the code but I suspect that the first problem is that your protected-mode code segment 0x8 has base of 0x00000000 while the offset of StartProtectedMode label is calculated relative to 0x7C0 real-mode segment.
Post 24 Sep 2018, 11:17
View user's profile Send private message Visit poster's website Reply with quote
Fulgurance



Joined: 27 Nov 2017
Posts: 276
Fulgurance 24 Sep 2018, 11:38
If you have any idea, help me please, i have changed my code, but crash again...
Code:
use16
org 0x0

mov ax,0x7C0
mov ds,ax

cli
lgdt [GDT32Descriptor]
mov eax,cr0
or eax,0x1
mov cr0,eax
jmp SetupProtectedMode

SetupProtectedMode:
mov ax,0x10
mov ds,ax
jmp dword 0x8:0x1000

GDT32:
.NullDescriptor:
    db 0, 0, 0, 0, 0, 0, 0, 0
.CodeDescriptor:
    db 0xFF, 0xFF, 0x0, 0x0, 0x0, 10011011b, 11011111b, 0x0
.DataDescriptor:
    db 0xFF, 0xFF, 0x0, 0x0, 0x0, 10010011b, 11011111b, 0x0
.End:

GDT32Descriptor:
.Limit:
dw GDT32.End - GDT32 - 1
.Base:
dd GDT32

use32
org 0x1000
StartProtectedMode:
mov byte [0xB8000],'A'
Main32:
jmp short Main32

db 510-($-$$)-63 dup 0x90
dw 0xAA55    
Post 24 Sep 2018, 11:38
View user's profile Send private message Reply with quote
DimonSoft



Joined: 03 Mar 2010
Posts: 1228
Location: Belarus
DimonSoft 24 Sep 2018, 11:43
Fulgurance wrote:
If you have any idea, help me please, i have changed my code, but crash again...
Code:
use16
org 0x0

mov ax,0x7C0
mov ds,ax

cli
lgdt [GDT32Descriptor]
mov eax,cr0
or eax,0x1
mov cr0,eax
jmp SetupProtectedMode

SetupProtectedMode:
mov ax,0x10
mov ds,ax
jmp dword 0x8:0x1000

GDT32:
.NullDescriptor:
    db 0, 0, 0, 0, 0, 0, 0, 0
.CodeDescriptor:
    db 0xFF, 0xFF, 0x0, 0x0, 0x0, 10011011b, 11011111b, 0x0
.DataDescriptor:
    db 0xFF, 0xFF, 0x0, 0x0, 0x0, 10010011b, 11011111b, 0x0
.End:

GDT32Descriptor:
.Limit:
dw GDT32.End - GDT32 - 1
.Base:
dd GDT32

use32
org 0x1000
StartProtectedMode:
mov byte [0xB8000],'A'
Main32:
jmp short Main32

db 510-($-$$)-63 dup 0x90
dw 0xAA55    

org directive doesn’t make your code magically appear at the specified offset in memory at runtime. It’s not what the directive is for.
Post 24 Sep 2018, 11:43
View user's profile Send private message Visit poster's website Reply with quote
Fulgurance



Joined: 27 Nov 2017
Posts: 276
Fulgurance 24 Sep 2018, 14:21
Okay, but how I do that ? I don’t know

Have I must load it into ram before with interrupt ?
Post 24 Sep 2018, 14:21
View user's profile Send private message Reply with quote
DimonSoft



Joined: 03 Mar 2010
Posts: 1228
Location: Belarus
DimonSoft 24 Sep 2018, 15:41
The meaning of org directive is described in FASM.pdf, chapter 2.2.4. You’ll also need a good understanding of what is placed where when the boot sector is starting its execution. Then you’ll be able to put all the pieces together and find a solution. I guess, only one small fix is needed for the previous version of your code.
Post 24 Sep 2018, 15:41
View user's profile Send private message Visit poster's website Reply with quote
Fulgurance



Joined: 27 Nov 2017
Posts: 276
Fulgurance 24 Sep 2018, 16:52
If i understand good, i think i need to set first org directive with
Code:
org 0x7C00    
, because calcul of adressing is with start adress of boot sector. (in my first post of my code)

But when i do that, i have already a crash ...

I'm soo sad ... i don't understand ...

EDIT: I have found my problem, in web site example with nasm, he use
Code:
jmp dword    
. When i remove dword, it's work fine
Post 24 Sep 2018, 16:52
View user's profile Send private message Reply with quote
DimonSoft



Joined: 03 Mar 2010
Posts: 1228
Location: Belarus
DimonSoft 24 Sep 2018, 22:55
Fulgurance wrote:
If i understand good, i think i need to set first org directive with
Code:
org 0x7C00    
, because calcul of adressing is with start adress of boot sector. (in my first post of my code)

But when i do that, i have already a crash ...

I haven’t said it’s the only problem. It was just the first one I noticed.

Fulgurance wrote:
EDIT: I have found my problem, in web site example with nasm, he use
Code:
jmp dword    
. When i remove dword, it's work fine

Copying someone else’s code is always bad. Trying to compile it with another toolset is even more asking for trouble. Noone expects a cat to bark, right?
Post 24 Sep 2018, 22:55
View user's profile Send private message Visit poster's website Reply with quote
edfed



Joined: 20 Feb 2006
Posts: 4330
Location: Now
edfed 28 Nov 2018, 12:47
an old code that works, my minimal set to boot and switch in pm
Code:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;boot and protected mode switch ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
        org 7C00h               ; where the binary should be loaded in ram
boot:                           ; boot = 7c00h (org)
        cli                     ; disable interrupts, don't enable them if you don't set the idt
        lgdt fword[cs:gdt.size] ; load the gdt from [cs:gdt] 6 bytes pseudo descriptor
        mov eax,cr0             ; equivalent to "or cr0,1"
        or al,1                 ;   switches the CPU in protected mode-
        mov cr0,eax             ;   protected mode enable
        jmp gdt.code:.pmode     ; equivalent to "mov cs,gdt.data" + "mov ip,.pmode"
.pmode:                         ;   the first instruction right after pm enable
        use32                   ; code below is 32 bits
        mov ax,gdt.data         ;
        mov ds,ax               ; make ds = .data entry in gdt, flat linear adress space
        mov word[0b8000h],7441h ; put a red char 'A' in upper left corner, on grey background, just to show it works
        hlt                     ; halts the processor, then, it will consume less energy
        jmp $                   ; infinite loop
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
        align 8                 ; align on 8 byte boundary for optimal performance
gdt:    dw 0                    ; in order to align dword part of pseudo desciptor on dword boundary
.size   dw @f-gdt-1             ; word part of pseudo desciptor, size of gdt in bytes
.linear dd gdt                  ; dword part of pseudo descriptor, linear base adress
.code=$-gdt                     ; first entry in gdt (8*1)
dw 0ffffh,0                     ;   4Gbytes, start at linear 0
db 0,10011010b,11001111b,0      ;   granularity = 64Kbytes, code segment, ring 0, read only,etc...
.data=$-gdt                     ; second entry in gdt (8*2)
dw 0ffffh,0                     ;   4Gbytes, start at linear 0
db 0,10010010b,11001111b,0      ;   granularity = 64Kbytes, data segment, ring 0, read/write,etc...
@@:                             ; used for gdt.size calculation
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
free =  510-(padding-$$)        ; define "free" bytes count
padding rb free                 ; reserve "free" bytes to make line below at offset 510
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
        dw 0aa55h               ; magic number boot mark, used by bios to test if valid boot sector
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;  
    


a very rare piece of code i fully commented Laughing
Post 28 Nov 2018, 12:47
View user's profile Send private message Visit poster's website Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20299
Location: In your JS exploiting you and your system
revolution 28 Nov 2018, 13:04
This line:
Code:
        align 8                 ; align on 8 byte boundary for optimal performance    
"optimal performance" for a boot loader that executes only once, okay maybe useful I guess. But then you put in the extra dw to misalign the descriptors. The CPU will load the entire descriptor first, before decoding the values within it, so the position of dd is not important, only the position of the first byte of the descriptor will dictate the alignment.
Post 28 Nov 2018, 13:04
View user's profile Send private message Visit poster's website Reply with quote
edfed



Joined: 20 Feb 2006
Posts: 4330
Location: Now
edfed 28 Nov 2018, 23:12
this trick was in the application note of pentium if my memory is not bad.
but yep, ones loaded in internal memory, no matter the alignement.
Post 28 Nov 2018, 23:12
View user's profile Send private message Visit poster's website Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.