it looks excellent code,although I'm not very familiar with ASM code,I will dig into it, thank you,Jakob!
by krishna. At 2018-08-17 22:00:40, "Jakob Bohm" <[email protected]> wrote: >On 17/08/2018 15:32, Jakob Bohm wrote: >> On 17/08/2018 12:27, krishnaLee wrote: >>> Hi, >>> as to my known,intel x64 cpu can work at 64-bit mode or >>> Compatibility mode, >>> so thery are two kind of x64-mode, >>> I find QEMU can run at each of them, >>> I want to write som C code to check it if it is running at 64-bit >>> mode or Compatibility mode, what's the key? >>> >> This mode is a bit in the segment descriptor referenced by the >> current CS register, the following or similar code should be >> able to check this(note that this code has to use only >> instructions that have the same encoding in all CPU modes!): >> >> ; UNTESTED HYPOTHETICAL CODE!!! >> >> ; First, check that we are not running in real or VM8086 >> ; mode, because then the following will not work >> ; (LAR will trigger an undefined opcode exception). >> ; Doing this is left as an exercise for the reader >> >> ; The following is valid in 16, 32 and 64 bit protected mode >> ; the instructions should have the same opcodes, they are >> ; shown here using the 32 bit mode Intel syntax >> .386 >> MOV EAX,CS >> LAR EAX,EAX >> JNZ SHORT modeerror >> SHR EAX,21 >> JCSHORT mode64 >> SHR EAX,1 >> JC SHORT mode32 >> mode16j: >> .286 >> ; Code here is 16 bit code and can use all 16 bit instructions >> JMP mode16 ; This can be a longer jmp now that we know the >> ; instruction encoding >> mode32j: >> .386 >> ; Code here is 32 bit code and can use all 32 bit instructions >> JMP mode32 ; This can be a longer jmp now that we know the >> ; instruction encoding >> mode64j: >> .amd64 ; Note, not sure what directive tells MASM to generate >> 64bit opcodes >> ; Code here is 64 bit code and can use all 64 bit instructions >> JMP mode64 ; This can be a longer jmp now that we know the >> ; instruction encoding >> modeerror: >> ; This really shouldn't happen! >> ; One possible way would be if something changed the CS descriptor >> ; in the descriptor table without reloading CS >> ; Code here is still restricted to mode independent instructions! >> >> ; Alternatively, a code sequence could be constructed that has different >> ; effects depending on CPU mode but doesn't directly query the CS >> ; descriptor table entry, avoiding the modeerror case above. >> >> ; UNTESTED HYPOTHETICAL CODE!!! >> >> ; Perhaps >> .386 >> XOR EAX,EAX ; XOR AX,AX if 16 bit mode >> NOT EAX ; 16 bit: AX is now 0FFFFh >> ; 32 bit: EAX is now 0FFFFFFFFh >> ; 64 bit: RAX is now 0FFFFFFFFFFFFFFFFh (UNTESTED) >> SHR EAX,16 >> JNC SHORT mode16j >> SHR EAX,16 >> JNC SHORT mode32j >> mode64j: >> ; as above >> mode32j: >> ; as above >> mode16j: >> .286 >> SMSW AX >> SHR AX,1 >> JNC SHORT mode16real >> ; Add code here to test if this is VM8086 mode or 16 bit >> ; protected mode >> ; First set up a stack, 4 byte aligned >> ; CODE MISSING >> ; Next do the classic tricks to detect if this is at least >> ; a 386, this involves using 16 bit PUSHF and POPF >> ; CODE MISSING >> ; The missing code should jump to mode16rj if < 386 >> ; Next use code to determine if in VM8086 mode, note that >> ; PUSHFD hides the desired EFLAGS bit from us, so another >> ; trick is needed >> ; CODE MISSING >> ; The missing code should jump to mode16rj if real mode >> mode16vj: >> .286 >> ; Code here is 16 bit code and can use all 16 bit instructions >> ; VM8086 mode >> JMP mode16v ; This can be a longer jmp now that we know the >> ; instruction encoding >> mode16rj: >> .286 >> ; Code here is 16 bit code and can use all 16 bit instructions >> ; Real mode, full CPU access! >> JMP mode16v ; This can be a longer jmp now that we know the >> ; instruction encoding >Corrections: > >In the first example, the first shift should be > SHR EAX,22 > >In the second example, the first shift should be > SHR EAX,17 > >And the entire 16 bit case needs to be regrouped: > >mode16rj: > .286 > ; Code here is 16 bit code and can use all 16 bit instructions > ; Real mode, full CPU access! > ; May or may not be the unofficial large-segment real mode > JMP mode16r ; This can be a longer jmp now that we know the > ; instruction encoding >mode16j: > .286 > ; 16 bit code, maybe protected, real, VM8086 or even > ; the unofficial large-segment real mode > > ; First set up a stack, 4 byte aligned > ; CODE MISSING OR ASSUME STACK ALREADY VALID > ; Next do the classic tricks to detect if this is at least > ; a 286, this involves using 16 bit PUSHF and POPF > ; CODE MISSING > ; The missing code should jump to mode16rj if < 286 > SMSW AX > SHR AX,1 > JNC SHORT mode16rj > ; So now it is protected mode or VM8086 mode > ; First check if at least a 386 (we know it's at least 286) > ; CODE MISSING > ; The missing code should jump to mode16pj if a 286 > ; Add code here to test if this is VM8086 mode or 16 bit > ; protected mode > ; Next use code to determine if in VM8086 mode, note that > ; PUSHFD hides the desired EFLAGS bit from us, so another > ; trick is needed > ; CODE MISSING > ; The missing code should jump to mode16vj if VM8086 mode >mode16pj: > .286 > ; Code here is 16 bit code and can use all 16 bit instructions > ; protected mode 16 bit > JMP mode16p ; This can be a longer jmp now that we know the > ; instruction encoding >mode16vj: > .286 > ; Code here is 16 bit code and can use all 16 bit instructions > ; VM8086 mode > JMP mode16v ; This can be a longer jmp now that we know the > ; instruction encoding > >Enjoy > >Jakob >-- >Jakob Bohm, CIO, Partner, WiseMo A/S. https://www.wisemo.com >Transformervej 29, 2860 Søborg, Denmark. Direct +45 31 13 16 10 >This public discussion message is non-binding and may contain errors. >WiseMo - Remote Service Management for PCs, Phones and Embedded >
