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.
That *looks* like exactly what the comments say. It's picking descriptor 1 (after null descriptor 0) for the data segment from the loaded GDT. Since the code probably doesn't crash, descriptor 1 probably describes a data segment. More than that I can't really say, since I don't have the rest of the code. Share?
The purpose of the two statements to extend ds, that is, make its limit 4 gigabytes (normal real mode segment limits are 64k). The use of bx in particular isn't important. It could have been any other register that you can load segment registers from (well, not ax in this example, unless you save and restore it).
Once ds has been extended, you can restore its original value of 0, and it will have a base of 0 and a limit of 4 gigabytes. You can then use 32-bit addressing for data, while still being in real mode. BIOS and string operations still use 16 bit addressing, however.
This is a bit difficult for me because I have just started OS developing.. I don't know much about GDT..
But now I think I got the point: lgdt instruction loads the global descriptor table and the beginning of the table is 0 (gdt-variable is 0 and passed as a parameter as the beginning of the table) and then memory address 0x00 is null descriptor and one descriptor is a byte long(??) so the descriptor number 1 is 0x08(because of null descriptor), number 2 is 0x80(??).
Is the descriptor number 1 for data segment? ???
My understanding of the code is that it loads DS with the offset of the descriptor in the GDT that describes the segment that will be used for data access. You can't do this directly (using something like "mov DS,0x08"), so you have to put the value into BX (or another register) first. Once DS is set, the values in the descriptor such as base, length, limit, and other gubbins are used to define exactly what memory will be accessed when you do something like "mov [DS:CX], 0xFFFF".
The next descriptor (number 2) is at offset 0x10 (16 bytes) from the start of the GDT. Number 3 is at 0x18 (24 bytes in), and so on....
I'm new to this too so I could be talking complete rubbish.
jimboynugget wrote:
My understanding of the code is that it loads DS with the offset of the descriptor in the GDT that describes the segment that will be used for data access.
That's almost correct, but just a slight bit off. It's the offset (which is always 8-byte aligned), but the lowest 3 bits aren't always 0. The 3rd bit from the right is for choosing between the GDT and the LDT and the 2nd and 1st bit are for the selector privilege level (from 0-3). So, 0x08 is the first valid one in the GDT, 0x14 is the second valid one in the LDT, 0x17 is the same but then in PL3 etc.
I'm new to this too so I could be talking complete rubbish.
Is there a website where I could find the numbers of different descriptors? I mean 0 is null descriptor, 1 is data segment descriptor...? Where is the whole list of them?
And what means that, I have to create/set up my own GDT when entering to pmode? Do I just have to set the right values to segment registers from the right descriptors like above with the DS register?
The first descriptor is always null, but after that it depends on how the particular GDT is laid out (that is, what's actually in it). In the "baby steps #7" the GDT has only two entries, a null (required), and a flat data.
One could just as well have a GDT with a null, flat code, and flat data. In which case you'd load ds with 0x10.
Just for the record, the first isn't just null, it's never used. Loading values below 4 should always give you a null selector even though the GDT may contain something else instead. You can then use those 8 bytes for something else