VOGONS

Common searches


First post, by videogamer555

User metadata
Rank Member
Rank
Member

I've been reading about setting up protected mode, and I found this good article about the GDT (Global Descriptor Table) http://wiki.osdev.org/Global_Descriptor_Table , but I noticed something peculiar. It says that data segments can be set to read-write, or read-only, while code segments can be read-execute or execute-only. So it's not possible to write to a code segment in protected mode? I'm pretty sure it is possible, because I know there many programs that use self-modifying code, even in Windows (often times this is used for compressed EXE files, where it has a small initial unzipper code that decompresses the main code, and then writes the decompressed code into the code segment to be executed). If writing to a code segment was not possible, compressed EXE files wouldn't be possible.

Can somebody explain how this works, such as how to set the flag bits in the GDT to permit writing to a data segment?

Reply 2 of 10, by vladstamate

User metadata
Rank Oldbie
Rank
Oldbie

Nothing stops you from having 2 GDT entries one selected by CS where read bit is on and one selected by DS where write bit is on. As long as you write to [DS:offset] you are good then you can jump to CS:offset.

However on more modern CPUs (read 64bit) and more modern OSes self modifying code does not really work like in old days due to the presence of NX bit in the page table. A month or so ago I tried code like that on OSX and it did not work. mprotect failed to make the code segment writeble and I could not self modify my code.

YouTube channel: https://www.youtube.com/channel/UC7HbC_nq8t1S9l7qGYL0mTA
Collection: http://www.digiloguemuseum.com/index.html
Emulator: https://sites.google.com/site/capex86/
Raytracer: https://sites.google.com/site/opaqueraytracer/

Reply 3 of 10, by videogamer555

User metadata
Rank Member
Rank
Member
vladstamate wrote:

Nothing stops you from having 2 GDT entries one selected by CS where read bit is on and one selected by DS where write bit is on. As long as you write to [DS:offset] you are good then you can jump to CS:offset.

However on more modern CPUs (read 64bit) and more modern OSes self modifying code does not really work like in old days due to the presence of NX bit in the page table. A month or so ago I tried code like that on OSX and it did not work. mprotect failed to make the code segment writeble and I could not self modify my code.

If I'm not mistaken, execution pointer modifying instructions like JMP and CALL automatically use CS segment register, while memory writing instructions like MOV and MOVSB automatically use the DS segment register. So there's no need to manually specify the segment being used.

I've got another question about this. After setting up the GDT with the LGDT opcode, your next command must be a far jump to some usable code, right? But why? Until you actually activate protected mode (setting CR0's bit-0 to 1), the GDT has no effect on execution. The GDT has no effect in real mode. So what exactly is the proper way to setup protected mode? Is it something like this?

1) Set the GDT entries as desired
2) enter protected mode via setting the first bit of CR0 to 1
3) perform far jump to first executable byte in your protected mode code segment

Or is it more like this?
1) Set the GDT entries as desired
2) Perform far jump to any valid code, just to make sure that you are following the proper way of doing things
3) Enter protected mode via setting the first bit of CR0 to 1, and now the CPU execution pointer will automatically jump to the first byte of the code segment you configured for protected mode in the GDT

Reply 5 of 10, by Qbix

User metadata
Rank DOSBox Author
Rank
DOSBox Author

It's been five hours.
Relax.

Last edited by Qbix on 2017-01-06, 11:46. Edited 1 time in total.
Reason: wording

Water flows down the stream
How to ask questions the smart way!

Reply 6 of 10, by ynari

User metadata
Rank Member
Rank
Member

You're asking basic questions that have been answered hundred of times elsewhere, and Vogons is not the right place to ask in any case.

Download the Intel instruction manuals and search on Google. You'll get far more informative and immediate answers.

Not to mention the large amount of free operating system code out there.

Reply 7 of 10, by vladstamate

User metadata
Rank Oldbie
Rank
Oldbie

You need to do the jump last. What the jump does is it forces the CPU to reload the CS. The CPU then detects that it is in Protected Mode and therefore rather than using the CS at face value it uses it instead to to index in GDT. Also a far jump will clear the prefetch queue. That is why the jump is done last.

In reality however you need a bit more code than the 3 steps you outlined, because if nothing else, few cycles later when IRQ1 happens (the timer interrupt) your IDT is not set up and you'll hit a General Protection Fault. Check this page for more detailed steps.

For a very simple code to enter PM and print something on the screen look here. Notice the important bits like executing CLI so you do not get any IRQs (except NMI). They are missing a far jump but you can easily add that.

YouTube channel: https://www.youtube.com/channel/UC7HbC_nq8t1S9l7qGYL0mTA
Collection: http://www.digiloguemuseum.com/index.html
Emulator: https://sites.google.com/site/capex86/
Raytracer: https://sites.google.com/site/opaqueraytracer/

Reply 8 of 10, by videogamer555

User metadata
Rank Member
Rank
Member
vladstamate wrote:

You need to do the jump last. What the jump does is it forces the CPU to reload the CS. The CPU then detects that it is in Protected Mode and therefore rather than using the CS at face value it uses it instead to to index in GDT. Also a far jump will clear the prefetch queue. That is why the jump is done last.

In reality however you need a bit more code than the 3 steps you outlined, because if nothing else, few cycles later when IRQ1 happens (the timer interrupt) your IDT is not set up and you'll hit a General Protection Fault. Check this page for more detailed steps.

For a very simple code to enter PM and print something on the screen look here. Notice the important bits like executing CLI so you do not get any IRQs (except NMI). They are missing a far jump but you can easily add that.

So can I just ignore NMI? How likely is NMI to happen at any given moment?

Reply 9 of 10, by vladstamate

User metadata
Rank Oldbie
Rank
Oldbie

Depends on what you want to do. If you are running in DOSBox then you can probably ignore NMIs. You can also mask them:

IN 70h, AL
AND AL, 01111111b
OUT 70h, AL

YouTube channel: https://www.youtube.com/channel/UC7HbC_nq8t1S9l7qGYL0mTA
Collection: http://www.digiloguemuseum.com/index.html
Emulator: https://sites.google.com/site/capex86/
Raytracer: https://sites.google.com/site/opaqueraytracer/

Reply 10 of 10, by videogamer555

User metadata
Rank Member
Rank
Member

I created a new thread, specifically about debuging my code that I'm currently using to switch to 32bit protected mode. Unfortunately, it has an error on the very next line of code it runs after the far jump. If you are skilled in debugging assembly code, please have a look at my code and explain why it's not working.
Heres the link to my new thread Why is 32bit Protected Mode not working in DOS Box?