Re: jump far after setting up protected mode
Posted: Mon Apr 13, 2020 9:03 am
In that case, the problem lies with the common source of misinformation which has given practically everyone who visits this site a flawed understanding of the x86 architecture. It is probably either the wiki, or some recommended link people will click on, or maybe some top result on google. The author of the tutorial you are following seems to be hopelessly confused himself. This probably originates back in the day when the internet was in its beginnings and you couldn't just download the manual.
In protected mode (CR0.PM=1 and EFLAGS.VM=0), instructions that load segment registers will interpret the operand as a GDT or LDT selector, and IDTR points to a table of interrupt descriptors. In real mode or virtual 8086 mode (CR0.PM=0 or EFLAGS.VM=1), loading a segment register will set the segment base equal to the selector shifted left by 4, and IDTR points to a table of 16-bit far pointers. That's the main difference.
The D/B field of the current CS determines the encoding of operand and address sizes. All it does is that when clear, they are 16-bit when no prefix is present, and 66h and 67h prefixes change the operand size or address size to 32 bits, respectively. When set, it's the other way around.
The D/B field of the current SS determines whether SP or ESP is used for stack operations.
The D/B field of an expand-down data segment determines whether the upper limit is 0ffffh or 0ffffffffh. Expand-down data segments are rarely used.
It just so happens that the D/B field of all segment registers is cleared on reset, and every limit is set to 0ffffh, and they are inaccessible in real mode. Therefore, to use a default size of 32 bits, as well as offsets greater than 0ffffh, you would have to enter protected mode first. In the process of copy pasting tutorials, which was a popular thing to do back then, some kids therefore conflated the various mechanisms involved, resulting in a lot of people being confused even to this day.
In protected mode (CR0.PM=1 and EFLAGS.VM=0), instructions that load segment registers will interpret the operand as a GDT or LDT selector, and IDTR points to a table of interrupt descriptors. In real mode or virtual 8086 mode (CR0.PM=0 or EFLAGS.VM=1), loading a segment register will set the segment base equal to the selector shifted left by 4, and IDTR points to a table of 16-bit far pointers. That's the main difference.
The D/B field of the current CS determines the encoding of operand and address sizes. All it does is that when clear, they are 16-bit when no prefix is present, and 66h and 67h prefixes change the operand size or address size to 32 bits, respectively. When set, it's the other way around.
The D/B field of the current SS determines whether SP or ESP is used for stack operations.
The D/B field of an expand-down data segment determines whether the upper limit is 0ffffh or 0ffffffffh. Expand-down data segments are rarely used.
It just so happens that the D/B field of all segment registers is cleared on reset, and every limit is set to 0ffffh, and they are inaccessible in real mode. Therefore, to use a default size of 32 bits, as well as offsets greater than 0ffffh, you would have to enter protected mode first. In the process of copy pasting tutorials, which was a popular thing to do back then, some kids therefore conflated the various mechanisms involved, resulting in a lot of people being confused even to this day.