User:Johnburger/Demo/Demo.inc

From OSDev Wiki
Jump to: navigation, search

This file contains most of the configurable values used by the Demonstrator. You can modify other values, but you need a deeper understanding of what they are, and how they affect other things in the system, before you can change them willy-nilly. (If you only willy change them, they should work. Go to the full nilly, and I'm not responsible...)

Identifier Description
BIOS.VGA.90x60 Defining this will make the Boot Code change the screen to 90x60 text mode instead of 80x50 (the default). Note that not every system supports this mode - the versions of VMware that I tried did, while my late-generation laptops didn't.
Timer.Tick Changing this changes how many times a second the Timer will interrupt the PC. The Demonstrator changes tasks on every Timer Tick (there's also a Yield function...), so you can change this value and watch what happens.
Window.Width
Window.Height
Changing these values has the effect of changing how many Tasks are created at run-time. Since each Task bounces a ball around its individual screen area, a larger area means fewer Tasks. A smaller area is intriguing: if it's too small to even draw a border, it doesn't bother; and if the area is 1x1, rather than bounce the ball it simply sits there and "rotates" - increments to show you that something is happening.

An interesting demonstration is to enable BIOS.VGA.90x60 (above), and set these to 1x1. The result is so many tasks that it overflows the maximum number of '386 hardware Tasks - at least, it does the way I've set them up. Each Task has its own LDT, which means there's only room for a little less than 4,100 Tasks.

User.Ball
User.BallColour
User.FrameColour
These are merely:
  • The character representing the Ball that bounces around;
  • The value for the colour to use for the Ball;
  • The value for the colour to use for the Frame
User.Delay Changing this value merely alters the delay between updates of the Ball position. The code puts the CPU in a busy-waiting loop (which could be time-sliced away at any moment) before returning to work out the next position for the ball.

There are two other scheduling techniques you can try, and they're both commented out in the User code:

  • The Halt technique tells the CPU to Halt the current Task until the next interrupt. This is (of course) very unfair to the other Tasks:
    • "Hey! If you're not using the CPU, why can't I?"
    • The alternate argument is: "I'd use all of my timeslice anyway, just spinning my wheels. At least this way I'm not using CPU power..."
  • The Yield technique tells the system to immediately switch to the next waiting Task, and don't wait for the Timer tick.


Demo/Demo.inc

;
; Demo.inc
;
 
; These are definitions for the rest of the program. You can experiment by
; changing them. Some expect to be changed (these first few), while others
; will have far-reaching impacts.
;
 
; This %define changes things to invoke the BIOS to show more text:
;%define         BIOS.VGA.90x60 ; Allow use of 90x60 VGA (not universal!)
 
; Change these to (almost) whatever you'd like. If you're too extreme, you'll
; get assemble-time errors. Others you won't know until you try...
; For example, Timer.Tick is limited on virtualisation programs like VMware,
; so that even programming ludicrous values will result in staid performance.
; However, on real hardware there isn't that sort of control. Go on, set the
; Timer to 1,000,000 times a second - I dare you!
Timer.Tick      EQU             1000    ; Number of Timer Interrupts a second
Window.Width    EQU             8       ; Width of each Task's Window
Window.Height   EQU             6       ; Height of each Task's Window
 
User.Ball       EQU             1       ; Try 3: it is an OEM 'Heart' symbol
User.BallColour EQU             Dev.VGA.BlueBack  | Dev.VGA.White
User.FrameColour EQU            Dev.VGA.GreenBack | Dev.VGA.White
User.Delay      EQU             0FFFFh  ; How long to 'idle'the Bounce animation
 
; A useful pseudo-instruction to invoke the built-in Debugger - after it's set up!
%define         DEBUG           DB 0CCh ; INT 3 - NASM assembles this as 0CD 03h
 
; Another macro for debugging. Enable Single Step debugging - after it's set up!
%macro          TRACE           0
                PUSHFD
                OR      WORD    [ESP],x86.EFlags.TF
                POPFD
%endmacro
 
; The following is the memory map for this Demonstration. Note that some of the
; areas are left over from the BIOS - I'm simply working around those.
IVT.Base        EQU             x86.IVT.Base
IVT.Size        EQU             x86.IVT.Size
BDA.Base        EQU             BIOS.BDA.Base
BDA.Size        EQU             BIOS.BDA.Size
Data.Base       EQU             BDA.Base + BDA.Size
Data.Size       EQU             IDT.Base - Data.Base
 
IDT.Base        EQU             Code.Base - IDT.Max ; Final address of IDT
IDT.Max         EQU             x86.Ints * x86.Desc_size ; Full size of IDT
 
Code.Base       EQU             1000h
 
Load.Base       EQU             IDT.Start       ; Load from start of defined IDT
Load.Max        EQU             8 * BIOS.Disk.Sector.Size ; See Boot/Load.inc for why
 
; This will be the first-available RAM after everything else is initialised
Demo.First      EQU             Load.Base + Load.Size + GDT.Size + Exec.Stack.Size
 
Exec.Stack.Top  EQU             Demo.First      ; This is the TOP of an Expand-Down stack
Exec.Stack.Size EQU             1000h
 
; The PICs need to be re-based to get them away from the Intel-reserved interrupts
PIC.A.Base      EQU             20h
PIC.B.Base      EQU             28h
 
; See Ints/Timer.inc for a discussion on this (significant!) definition
System.TSS      EQU             x86.Desc.Mem.Gran.Avail
 
; This is the Descriptor for the Alias for the Descriptor Table that holds it
DT.Alias        EQU             x86.Desc_size
 
; The following structure is held in the first (NULL) GDT entry. It holds the
; information about the current state of the GDT: how big it is, and which
; entries have been returned.
; It is designed to enable the following instruction to be used:
;         LGDT  [GDT.Alloc.Pseudo]
; This is accomplished by:
; 1) Storing the linear base address of the GDT in .Pseudo.Base
; 2) Storing the current GDT size in .Pseudo.Size
; 3) As entries are freed, adding them to the .Free list (this uses the entries
;    themselves to store the next Free one, or 0 to end the list).
                STRUC           GDT.Alloc
.Free           RESW            1       ; Index to first Free Descriptor, or 0
.Pseudo         EQU             $       ; You can do LGDT [GDT.Alloc.Pseudo]
.Pseudo.Limit   EQU             $
.Limit          RESW            1       ; Last allocated Descriptor
.Pseudo.Base    RESD            1       ; GDT.Base, as part of a pseudo-descriptor
                ENDSTRUC
 
; Like the GDT, the following structure is held in the first LDT entry - even
; though this is a valid entry according to Intel's definition.
; But by putting it there, and setting it up so that the important fields
; overlap the same fields in GDT.Alloc, the same code can be used to
; allocate Descriptors in either table.
; The "important fields" are simply .Free and .Limit
                STRUC           LDT.Alloc
.Free           RESW            1       ; Index to first Free Descriptor or 0
.Limit          RESW            1       ; Last (ever) allocated Descriptor
                RESB            1       ; Reserved
.Type           RESB            1       ; Make sure any attempt at access fails!
.GDT            RESW            1       ; This is the LDT's entry in the GDT
                ENDSTRUC
 
; As stated above, the two ?DT.Alloc structures have common elements:
                STRUC           DT.Alloc
.Free           RESW            1       ; Index to first Free Descriptor, or 0
.Limit          RESW            1       ; Last allocated Descriptor
                ENDSTRUC
Personal tools
Namespaces
Variants
Actions
Navigation
About
Toolbox