Page 4 of 4

Re: Debugging help for protected mode entry+exit experiment

Posted: Sat Sep 26, 2020 10:58 am
by awik
Octocontrabass wrote:
awik wrote:I am wondering why ...
No reason. Neither one follows the Intel requirements (you must put the far JMP or far CALL immediately after the instruction that changes CR0.PE, with no other instructions between) so there is no guarantee that either will work.
Intel's sample code does only a short/near jump to clear the prefetch queue (lines 175-182).

Anyway, if there is anything I've confirmed and learned repeatedly during these efforts, it's that RETF is just fine, and I'm going to stay with it.
awik wrote:Apparently the attributes of a protected mode segment in VMware are "sticky": they won't go away even after a return to real-mode and reloading the segment register with a real mode value.
This is true of bare metal as well, and the Intel manual says as much in the section about returning to real mode.
That (the metal part) decides it. As a matter of fact, I prefer this behaviour, because it means that you can call DOS with "big" segment limits and have them stay in effect. As for the documentation, Intel could have emphasised this a bit more. Many parts of their manuals seem to imply that real mode segments always have a 0xFFFF limit.

-Albert.

Re: Debugging help for protected mode entry+exit experiment

Posted: Sat Sep 26, 2020 11:45 am
by Octocontrabass
awik wrote:Intel's sample code does only a short/near jump to clear the prefetch queue (lines 175-182).
Intel's sample code hasn't been updated since 1992. I'm sure it works fine on a 386 or 486, but you need a far JMP if you want it to work on newer CPUs.
awik wrote:That (the metal part) decides it. As a matter of fact, I prefer this behaviour, because it means that you can call DOS with "big" segment limits and have them stay in effect.
Microsoft calls it "big real mode" in the HIMEM.SYS source code, but most other sources refer to it as "unreal mode".

Other segment attributes may also stay in effect across mode switches, but unlike limits, you can't count on that behavior being consistent across hardware or emulators.
awik wrote:As for the documentation, Intel could have emphasised this a bit more. Many parts of their manuals seem to imply that real mode segments always have a 0xFFFF limit.
Intel doesn't want you to know about it. There's some evidence that the original 386 design wasn't supposed to allow returning to real mode, much like the 286, and someone (likely from Microsoft or Compaq) pressured Intel into changing it at the last minute. It would explain why the microcode-heavy 386 lacks any mechanism to enforce real-mode segment behavior when returning to real mode, and why Intel's documentation avoids explaining exactly what's going on.

Re: Debugging help for protected mode entry+exit experiment

Posted: Sat Sep 26, 2020 12:17 pm
by alexfru
awik wrote:Apparently the attributes of a protected mode segment in VMware are "sticky": they won't go away even after a return to real-mode and reloading the segment register with a real mode value.
Well, what wasn't clear in the manual?
intel wrote: 4. Load segment registers SS, DS, ES, FS, and GS with a selector for a descriptor
containing the following values, which are appropriate for real-address mode:
— Limit = 64 KBytes (0FFFFH)
— Byte granular (G = 0)
— Expand up (E = 0)
— Writable (W = 1)
— Present (P = 1)
— Base = any value
The segment registers must be loaded with non-null segment selectors or the
segment registers will be unusable in real-address mode. Note that if the
segment registers are not reloaded, execution continues using the descriptor
attributes loaded during protected mode.

Re: Debugging help for protected mode entry+exit experiment

Posted: Sat Sep 26, 2020 11:41 pm
by awik
alexfru wrote:
awik wrote:Apparently the attributes of a protected mode segment in VMware are "sticky": they won't go away even after a return to real-mode and reloading the segment register with a real mode value.
Well, what wasn't clear in the manual?
intel wrote: 4. Load segment registers SS, DS, ES, FS, and GS with a selector for a descriptor
containing the following values, which are appropriate for real-address mode:
— Limit = 64 KBytes (0FFFFH)
— Byte granular (G = 0)
— Expand up (E = 0)
— Writable (W = 1)
— Present (P = 1)
— Base = any value
The segment registers must be loaded with non-null segment selectors or the
segment registers will be unusable in real-address mode. Note that if the
segment registers are not reloaded, execution continues using the descriptor
attributes loaded during protected mode.
The main problem with it, is that I did not find (or remember or understand) that passage until *after* I needed it. It is not apparent from the rest of the manual (in fact, almost on the contrary), even in places where it would be relevant to mention. I was also confused by the statements that the *base* of a real mode segment *is* reset when you load a segment register -- I thought the same happened with the limit.

-Albert.

Re: Debugging help for protected mode entry+exit experiment

Posted: Sun Sep 27, 2020 12:33 am
by alexfru
awik wrote:
intel wrote: ...
The main problem with it, is that I did not find (or remember or understand) that passage until *after* I needed it. It is not apparent from the rest of the manual (in fact, almost on the contrary), even in places where it would be relevant to mention. I was also confused by the statements that the *base* of a real mode segment *is* reset when you load a segment register -- I thought the same happened with the limit.
Got it, yes, it happens. The manual is not a particularly easy read. You often need to go through many of mentions of something in it in order to get the picture. And then come back to some of them and reread them.

Re: Debugging help for protected mode entry+exit experiment

Posted: Sun Nov 08, 2020 10:17 am
by awik
Hi all,

I've come a long way since I last posted. I have in fact reached one of the original goals, which was to enter V86 mode. For anyone who is interested, here is the latest revision:
v86.zip

Currently, I'm trying to figure out how, inside my V86 monitor, to do an INT 21h call on behalf of (in the context of) the interrupted task (the task that generated the GPF/INT 0Dh).

Another question that has come up, is whether figure 16-4 of the Intel system programmer's manual applies only to V86 mode or to regular protected mode (with privilege level transition) as well? If you can't find this figure, basically, it illustrates the stack layout at the point where an interrupt/exception handler has been called. It shows that the interrupted task's segment registers are all saved on the interrupt/exception handler's stack.

Cheers,
Albert.

Re: Debugging help for protected mode entry+exit experiment

Posted: Sun Nov 08, 2020 11:02 am
by Gigasoft
Currently, I'm trying to figure out how, inside my V86 monitor, to do an INT 21h call on behalf of (in the context of) the interrupted task (the task that generated the GPF/INT 0Dh).
Are you writing a DOS emulator or just running DOS inside V86 mode?
Another question that has come up, is whether figure 16-4 of the Intel system programmer's manual applies only to V86 mode or to regular protected mode (with privilege level transition) as well?
No, DS, ES, FS and GS are only present when entering or leaving V86 mode.

Re: Debugging help for protected mode entry+exit experiment

Posted: Sun Nov 08, 2020 11:52 am
by awik
Gigasoft wrote:
Currently, I'm trying to figure out how, inside my V86 monitor, to do an INT 21h call on behalf of (in the context of) the interrupted task (the task that generated the GPF/INT 0Dh).
Are you writing a DOS emulator or just running DOS inside V86 mode?
The latter. I don't know if it is realistic, but the ideal is to implement a DOS multitasker loosely based on the VxD layer (ie. kernel mode) of Win3.x/9x. I have little interest in writing a clone of the Win16/32/64 API, but possibly a platform upon which such a project (by someone else) could be based.
Another question that has come up, is whether figure 16-4 of the Intel system programmer's manual applies only to V86 mode or to regular protected mode (with privilege level transition) as well?
No, DS, ES, FS and GS are only present when entering or leaving V86 mode.
Thanks.

-Albert.

Success!

Posted: Wed Nov 11, 2020 9:00 am
by awik
I've had a lot of success with this project lately.

I can now return to DOS while in V86 mode, and even run real-mode programs successfully. This is despite that my V86 monitor is very simple. Basically, it just handles INT xx and IN/OUT. On the other hand, the VM runs with IOPL=3 and a clear I/O bitmap (meaning allowed without generating a fault) for ports 0-4096.

Obviously, protected mode programs cannot run properly, because the machine is already in protected mode, and I haven't implemented DPMI or VCPI.

The NASM assembly language source code is 1347 lines, and the binary .COM file is 3184 bytes. I don't know if that is compact or not for a program of this nature. Alex's TUT15 .EXE is about 15K, but that is not a fair comparison because it is written largely in C language.

The source and binary are available at:
https://drive.google.com/file/d/1utPCWh ... sp=sharing

Cheerio,
Albert.

Re: Debugging help for protected mode entry+exit experiment

Posted: Sun Nov 15, 2020 5:24 am
by awik
Hi all,

I'm trying to modify my program to use only one TSS, and trying to enter V86 mode through setting up the stack for an IRETD.

I'm getting an 0Ah (Invalid TSS) exception at the point of the IRETD. Does anyone see an obvious error with the following code?

Code: Select all

	mov	ax, cs
	mov	[bp+BSS_OLD_SEG], ax
	xor	dx, dx
	mov	dl, ah
	mov	cl, 4
	shr	dl, cl
	shl	ax, cl
...
	add	[ze_gdt.sel38+2], ax
	adc	[ze_gdt.sel38+4], dl
...
BITS 32
	xor	edx,edx
	mov	eax,cr3
	mov	[tss_0.pdbr],eax
	;
	xor	eax,eax
	mov	dword [tss_0.ssesp0],ring0_stack0_top
	mov	ax, ss
	mov	[tss_0.ssesp0+4],eax
	;
	mov	[tss_0.ldtr],edx
	;
	mov	ax, 0x38
	ltr	ax
	;
	; Set up stack for "return" to V86 mode.
	;
	mov	edx,esp
	xor	eax,eax
	push	eax		; dummy, unused
	mov	ax, [ebp+BSS_OLD_SEG]
	push	eax		; GS
	push	eax		; FS
	push	eax		; DS
	push	eax		; ES
	push	eax		; SS
	push	edx		; ESP
%define FLAGS_NT_BIT   14
%define FLAGS_VM_BIT   17  ; hex 11h
%define FLAGS_IOPL_BIT 12  ; actually 12 *and* 13.
%define FLAGS_IOPL_3 (3 << FLAGS_IOPL_BIT)
%define FLAGS_NT     (1 << FLAGS_NT_BIT)
%define FLAGS_VM     (1 << FLAGS_VM_BIT)
	pushfd
	pop	edx
	or	edx, FLAGS_VM | FLAGS_IOPL_3 | FLAGS_NT
	push	edx		; EFLAGS
	push	eax		; CS
	push	dword .v86_target_eip
	iretd			; "return" to V86 mode.
;--------
BITS 16
.v86_target_eip:
xor eax,eax
mov ax, cs
mov cx,0xB800
mov es, cx
mov di,(4*80*2)
...
ze_gdt:
	dd 0, 0		; entry 0: unused
...
.sel38: ; TSS (Task State Segment)
	dw (tss_0.end-tss_0)  ; +0  limit bits 0-15
	dw tss_0   ; +2  base addr. 0-15	-- must fixup
	db 0       ; +4  base addr. 16-23	--  "
	db 0x89    ; +5  PDdSType, *P=present, D=DPL, *S=0=sys.desc
	db 0x00    ; +6  G00ALimt, G=gran., A=avail.
	db 0x00    ; +7  base addr. 24-31
...
tss_0:
	dw 0		; +00  prev. task link
	dw 0		; +02  resv.
.ssesp0:dd 0		; +04  ring 0 ESP
	dw 0		; +08  ring 0 SS
	dw 0		; +0A  resv.
	dd 0		; +0C  ring 1 ESP
	dw 0		; +10  ring 1 SS
	dw 0		; +12  resv.
	dd 0		; +14  ring 2 ESP
	dw 0		; +18  ring 2 SS
	dw 0		; +1A  resv.
.pdbr:	dd 0		; +1C  CR3 (PDBR)
.eip:	dd 0		; +20  EIP
.eflags:dd 0		; +24  EFLAGS
.eax:	dd 0		; +28  EAX
	dd 0		; +2C  ECX
	dd 0		; +30  EDX
	dd 0		; +34  EBX
.esp:	dd 0		; +38  ESP
	dd 0		; +3C  EBP
	dd 0		; +40  ESI
	dd 0		; +44  EDI
	dw 0		; +48  ES
	dw 0		; +4A  resv.
.cs:	dw 0		; +4C  CS
	dw 0		; +4E  resv.
	dw 0		; +50  SS
	dw 0		; +52  resv.
	dw 0		; +54  DS
	dw 0		; +56  resv.
	dw 0		; +58  FS
	dw 0		; +5A  resv.
	dw 0		; +5C  GS
	dw 0		; +5E  resv.
.ldtr:	dw 0		; +60  LDTR
	dw 0		; +62  resv.
	dw 0		; +64  bit 0: Trap Flag, rest resv.
.iomapbase:
	dw .iomap-tss_0	; +66  I/O Map Base Address
.iomap:	db (4096/8) dup (0)
	db 0xFF
.end:
Regards,
Albert.

Re: Debugging help for protected mode entry+exit experiment

Posted: Sun Nov 15, 2020 8:07 am
by awik
OK, never mind, I solved it.

You need to clear the NT flag before trying to IRETD. On the other hand, it does not matter whether the NT flag is set in the EFLAGS image on the stack.

-Albert.