mikegonta wrote:The point is, that they don't work the same. The override prefix makes a 32 bit instruction out of a 16 bit opcode in RM16 andh0bby1 wrote:the rest i don't care if it's made in 32 or 16 bit, any of them should work the same
a 16 bit instruction out of the same opcode (which is 32 bit) in PM32.
There is also the issue of the near jmp, which has a 16 bit offset in RM16 and a 32 bit offset in PM32. In this case, when run
in PM32 the binary code will eat the next opcode as well.PM16 is a totally different story.normally opcode should be almost identical from real mode to 16 bit pm
the code will never be run in pm32, but in pm16, due to 16 bit code segment selector used in the far call/software interupt
normally you can write some code in a 16 bit section with an assembler, and it shouldn't care at all if the cpu is in real mode or protected mode to assemble the file, the opcode are identical and interpreted identically in pm16 and real mode, even with prefixes, only the way memory seg/ofset address are interpreted
it's more tricky for all the call mecanism that push return address in the stack, because the format of the address pushed depend on many things, i watched the documentation of iret instruction in intel manual, it's behavior depend on many thing, cpu flags, type of code segment and override, it's behavior is rather complex
like say you would make a routine to switch to real mode, and call it from 32 bit code, the 'ret' instruction of the function would most likely fail after the switch to real mode, because address passed on the stack are expected to be 2 16 bits values, whereas in 32 bit mode, the value pushed on the stack are 32 bit value for seg/ofset of the return address, even if the segment part is always 16 bit, it's still pushed as a 32 bit value as well as the ofset, so the ret function would return to wherever and mostly likely create a page fault, unless it's a near call to an address that fit in 16 bits, in which case it should still work in both case, but it would leave the two upper bytes of the return address on the stack
interupts are easier because the idt already contain a selector, so the cpu is smart enougth to format the stack depending on the segment selector of the idt, so you don't have to care about the parameters of software interupt or exception , they are always formated according to the bit value of the destination selector, but far call and far jumps are more tricky
but there is no 'true' pm16 mode, except on 286, but on all 32 bit cpu, pm16 is just protected mode executed in a 16 bit code segment, and it can use the same kind of trick with prefix to use 32 bit version of opcode, it works the same than real mode, pm16 is not a special cpu mode or anything like this, it's just a 32 bit flag is present on code segment selector that don't need the prefix overide and exepect default size of 32 bit and probably various other thing, but pm code executed in 16 bit segment behave the same than real mode in respect to operand implicit size etc
before what i was doing is switching to real mode from a protected mode 16 bit code segment, and doing all the real mode code in the 16 bit segment, the 16 bit code can be either targeted at real mode or protected mode, it doesn't change anything, the cpu can be switched from protected mode to real mode back and forth within a 16 bit code segment, just need to be carefull that segment register contain valid values for the mode selected, and segment registers are always 16 bits anyway, so they can be passed between pm32 and pm16 without problem, only ofset has to be 16 bit 'normally' unless you use operand size overide prefix, which is done automatically in any case by most compilers and assemblers
the semantic of 'far call' can be confusing between real mode and protected mode, because in real mode 'far call' really mean often that the address is so far away that it need to change the segment register value to reach it, and so it mean jump to a '32 bit address', but in 32 bit mode, near jump are already 32 bit, and the far jump is more about 'make a segment selector switch' , but it can do a selector switch just to change the mode of execution or privilege value to point at the same address , so it's not even really the same behavior than in real mode, you could do a near jump in 32 bit protected mode to any address of the system, but the far jump allow to change the segment selector , and can switch the execution between 32 and 16 mode