problem in saving current DOS state....

Hi,
I am a computer science and engg student. I am trying to do a project named "Multitasking under MS-DOS". It is not true multitasking( neither co-operative nor pre-emptive) just task switching.

If any one wants to change the task, he/she will press an hot key, then they can get the shell to change the task. For that i need to know what are all the things that is to be saved about DOS's current system state. I am planning to store the current system state in hard disk (as a file).

Please kindly help me quickly, because I have only 2 more months to finish the project.

Help me please.....

Yours,

--csanthosh--
«1

Comments

  • : Hi,
    : I am a computer science and engg student. I am trying to do a project named "Multitasking under MS-DOS". It is not true multitasking( neither co-operative nor pre-emptive) just task switching.
    :
    : If any one wants to change the task, he/she will press an hot key, then they can get the shell to change the task. For that i need to know what are all the things that is to be saved about DOS's current system state. I am planning to store the current system state in hard disk (as a file).
    :
    : Please kindly help me quickly, because I have only 2 more months to finish the project.
    :
    : Help me please.....
    :
    : Yours,
    :
    : --csanthosh--
    :

    Here's a quick and simple solution that will be fine as long as no extenders (like HIMEM.SYS) are running. Just save the entire meg of DOS addressing space. That way you'll protect the first tasks code and data when you load the second task, as a) they both will be executing in the same memory area, and b) DOS programs aren't that well-behaved. Don't forget to save the register state as well.


    "We can't do nothing and think someone else will make it right."
    -Kyoto Now, Bad Religion

  • :
    : Here's a quick and simple solution that will be fine as long as no extenders (like HIMEM.SYS) are running. Just save the entire meg of DOS addressing space. That way you'll protect the first tasks code and data when you load the second task, as a) they both will be executing in the same memory area, and b) DOS programs aren't that well-behaved. Don't forget to save the register state as well.
    :
    :
    : "We can't do nothing and think someone else will make it right."
    : -Kyoto Now, Bad Religion
    :
    :
    hello sir,

    I cann't get you. I have tried to save DOS's 1 mb of memory and restored it. the system got hang..

    --csanthosh---
  • :...
    :I cann't get you. I have tried to save DOS's 1 mb of memory and restored it. the system got hang..
    :
    : --csanthosh---
    :
    Hi,

    I'm not sure about this is that easy! There are parts of memory used by the BIOS (e.g. $0000:$0400 for the interrupt vector table). If you [red]just[/red] overwrite this parts of the memory, I think your system probably will hang. You'll have to assure all interrupts are suppressed for the moment you restore the memory. Therefore you can change the state of the PIC (Programable Interrupt Controller). I'm sorry I don't have any documentation for you, because I just have got a book about the PIC and it's in German :-(
    Another hint... Keep in mind, that programs could use extended memory (EMS or XMS) this sould be restored, too.
    Try to find out, which parts of the memory are reserved by DOS and save it. This should be a step forward, because all programs have to get their memory via DOS. A problem I see is the saving of the current register states?! In protected mode the CPU does this for you, you need to assure that your program does not change any of the registers. Further, do you know how to save the last value of the IP register! Don't forget to save all the flags (CF,ZF,...,OF).
    Can you see what I mean, I guess your project is far away from beeing trivial.

    greetings moo
  • Make sure you do a CLI before the copy and don't restore over your restoring code! Also, don't save your saving code!
  • : Make sure you do a CLI before the copy and don't restore over your restoring code! Also, don't save your saving code!
    :
    Sorry me again,
    I've got a few questions to blip:
    1) Why will a single cli work?
    2) how would you realize the saving of the IP register? Let's say a part of the tastmanager will extend the keyboard interrupt routine to be able to react on hot keys. This interrupt calls the routine for saving the current thread. How can one figure out, which thread is currently active, or better was active (now your taskmanager is) and especially where (value of CS and IP).

    sorry for the interruption
    greetings moo

  • : : Make sure you do a CLI before the copy and don't restore over your restoring code! Also, don't save your saving code!
    : :
    : Sorry me again,
    : I've got a few questions to blip:
    : 1) Why will a single cli work?
    : 2) how would you realize the saving of the IP register? Let's say a part of the tastmanager will extend the keyboard interrupt routine to be able to react on hot keys. This interrupt calls the routine for saving the current thread. How can one figure out, which thread is currently active, or better was active (now your taskmanager is) and especially where (value of CS and IP).
    :
    : sorry for the interruption
    : greetings moo
    :
    :
    CLI masks the interrupts from the CPU. When the interrupt flag is cleared the CPU will not check the PIC (or it has that effect) and interrupts will just be pending (with the exception of NMIs)

    Make sure that the file IO is synchronous and not asynchronous. hehe

    As for the IP it's easy enough to get. It's sitting right on the stack whenever a call or int is executed. You could use the following code to get the current IP (well close to it, you'll need to add to it for the code after next).

    call next
    next:
    pop ax

    Typically, though your routine will pluck it off the stack.

    How do you determine which TASK is currently active (as that was the original post). Well, that's easy. Your taskmanager should be MANAGING this and will know because the last task will be the last task the taskmanager started. In other words, you need to keep track. With the system this guy is making up, there will be no way whatsoever to tell in a reasonable amount of time from the information given unless you keep track.

    "We can't do nothing and think someone else will make it right."
    -Kyoto Now, Bad Religion

  • OK, I've been thinking of what you must save for each task: IVT (Interrupt Vector Table) and (almost) everything else in memory, PIC masks, current video mode (on restore, switch modes only if there is a change in modes across two tasks, also it'd be good if you saved all video registers), all CPU registers (PUSHAD, PUSH DS, PUSH ES, PUSH FS, PUSH GS, PUSHFD and then save SS:SP at the end of the file along with CS:IP (if there was a hardware int to initiate this, then CS:IP and flags are already saved on the stack)), and probably many other things. You will encounter many problems along the way (that's why I didn't write a multitasker a few months ago for myself) like overwriting DOS's file I/O tables and the switcher TSR itself. Another thing is that somewhere in DOS and/or BIOS code there is probably going to be a STI so before reading and writing data, so set the first PIC mask to 11111111b and the second to 10111111b (you might have to clear bit 7 if you have problems with a second HD).
  • hi,
    Thank you all for helping me. I don't think that this much problem will arise. I have found that DOS's SDA( swappable data area is having current DOS's state( i.e., PSP, DTA, DOS internal stack, Extended error information and etc.,).
    I am always thinking about current DOS state only. Now only I knew(from your answer) that the Video mode, PIC masks, IVT and all should be saved. Thank you once again for this.
    I got only this much information about the SDA. If anybody knows the detailed structure of SDA, tell me please...

    sample code to get SDA info,

    void getsda(unsigned *seg, unsigned *0ff, unsigned *bigsize,
    unsigned *smallsize)
    {
    union REGS i;
    union SREGS s;

    i.h.ax = 0x5d06;
    intdosx(&i, &i, &s);

    *seg = s.ds;
    *off = i.x.si;
    *bigsize = i.x.cx;
    *smallsize = i.x.dx;
    }

    here seg and off are segment and offset address of SDA. If DOS is busy 'bigsize' should be saved otherwise 'smallsize'.

    I know the port no 0x20 and 0x21 are related with PIC and it regulates the hardware interrupts according to priority. But other than this I don't know anything. Please tell me about masking and how to mask.

    thank you,

    --csanthosh--

    : OK, I've been thinking of what you must save for each task: IVT (Interrupt Vector Table) and (almost) everything else in memory, PIC masks, current video mode (on restore, switch modes only if there is a change in modes across two tasks, also it'd be good if you saved all video registers), all CPU registers (PUSHAD, PUSH DS, PUSH ES, PUSH FS, PUSH GS, PUSHFD and then save SS:SP at the end of the file along with CS:IP (if there was a hardware int to initiate this, then CS:IP and flags are already saved on the stack)), and probably many other things. You will encounter many problems along the way (that's why I didn't write a multitasker a few months ago for myself) like overwriting DOS's file I/O tables and the switcher TSR itself. Another thing is that somewhere in DOS and/or BIOS code there is probably going to be a STI so before reading and writing data, so set the first PIC mask to 11111111b and the second to 10111111b (you might have to clear bit 7 if you have problems with a second HD).
    :

  • About masking IRQs, it's extremely easy!

    Port 21h, read/write mask register for IRQs 0-7
    Each IRQ is controlled by its corresponding bit; if a bit is set the IRQ is masked, it is unmasked when the bit is clear.
    E.g. Mask IRQ 2:
    [code]in al,21h
    or al,00000100b ;Set bit 2.
    out 21h,al[/code]

    Port 0A1h, read/write mask register for IRQs 8-15
    Each IRQ is controlled by its corresponding bit+8; if a bit is set the IRQ is masked, it is unmasked when the bit is clear.
    E.g. Unmask IRQ8:
    [code]in al,0A1h
    and al,11111110b ;Clear bit 0.
    out 0A1h,al[/code]

    E.g.2 Check the status of IRQ14:
    [code]in al,0A1h
    test al,01000000b ;TEST bit 6. ZF if not masked, NZ if masked.[/code]
  • hi,

    thank you blip for explaining the concept of masking.
    What about SDA?

    ---csanthosh---

    : About masking IRQs, it's extremely easy!
    :
    : Port 21h, read/write mask register for IRQs 0-7
    : Each IRQ is controlled by its corresponding bit; if a bit is set the IRQ is masked, it is unmasked when the bit is clear.
    : E.g. Mask IRQ 2:
    : [code]in al,21h
    : or al,00000100b ;Set bit 2.
    : out 21h,al[/code]
    :
    : Port 0A1h, read/write mask register for IRQs 8-15
    : Each IRQ is controlled by its corresponding bit+8; if a bit is set the IRQ is masked, it is unmasked when the bit is clear.
    : E.g. Unmask IRQ8:
    : [code]in al,0A1h
    : and al,11111110b ;Clear bit 0.
    : out 0A1h,al[/code]
    :
    : E.g.2 Check the status of IRQ14:
    : [code]in al,0A1h
    : test al,01000000b ;TEST bit 6. ZF if not masked, NZ if masked.[/code]
    :

  • I have no idea about the SDA, I've never heard of it before, sorry.
  • [b][red]This message was edited by the Moderator at 2002-6-27 3:23:23[/red][/b][hr]
    If your switcher is going to always be used in real mode on a 386+, you can move the IVT by modifying IDTR to prevent programs from revectoring your switcher interrupt. When an interrupt occurs, do a PUSHF followed by a far call to the handler pointed to by it's IVT entry at the base of memory (not the relocated one). The only one(s) you don't call is/are any you revectored yourself.

    There's some more things you'll need to do if you plan to support programs that use any VESA services:
    [code]mov ax,4F03h ;Get video mode, works on standard VGA ones, too
    test ah,ah
    jnz CantUseVESAsoUseFunction1ChOfInt10h ;This is for pre-VESA video BIOSes.
    ;BX = Current VESA/VGA mode so save it somewhere!
    mov ax,4F02h ;Set VESA mode
    mov bx,81FFh ;This is a special mode that allows access to all video memory.
    int 10h
    SaveVidMem:
    ;Write segment 0A000h to the file.
    mov dx,cs:[BankNum]
    mov ax,4F05h ;Switch bank number.
    inc dx
    xor bx,bx ;This is important, look in Ralf Brown's for the reason.
    mov word ptr cs:[BankNum],dx
    int 10h
    test ah,ah
    jnz SaveVidMem
    ;More code...
    BankNum dw 0[/code]

    Restoration code:
    [code]
    ;I assume here you'd still be in mode 81FFh, so just get data from file and dump it into video memory.
    mov ax,4F02h ;Set VESA video mode.
    ;BX = video mode this task should be in, also works on standard VGA modes.
    int 10h

    [/code]



  • : If your switcher is going to always be used in real mode on a 386+, you can move the IVT by modifying IDTR to prevent programs from revectoring your switcher interrupt. When an interrupt occurs, do a PUSHF followed by a far call to the handler pointed to by it's IVT entry at the base of memory (not the relocated one). The only one(s) you don't call is/are any you revectored yourself.


    hello sir,
    I am sorry sir, I am not able to understand the above paragraph. please explain me with example.Particularly "you can move the IVT by modifying IDTR".
    what is IDTR?

    --csanthosh--
  • I'm sorry, I assumed you already knew about IDTR. Well, it is a 48-bit register that is supposed to be used in protected mode to give the processor the location and length of the IDT (Interrupt Descriptor Table). But ever since the 386 came along, you can also use it to relocate the IVT (Interrupt Vector Table) to some other place in memory, like this (and this is how I reccomend you use it):
    [code]
    ;Copy the IVT to it's new place here (using MOVSD, of course).
    xor eax,eax ;The value below needs to be zero-extended.
    mov ax,seg IDTr
    shl eax,4
    add dword ptr [IDTr],eax ;This will finish calculating the linear address.
    lidt fword ptr [IDTr] ;Load the IDTR with [IDTr].
    ;If LIDT won't compile, take it out and uncomment these lines:
    ;db 0Fh,1,1Eh
    ;dw offset IDTr

    ;...More of your code here.

    IDTr dd offset Free1KBspot ;You need a place that has 1KB of storage.
    dw 3FFh ;This is the length-1, 1KB.
    [/code]

    Did this help?
  • hello sir,
    Thank you for constantly helping to my project. But I know C language very well. I know assembly language very very little bit.
    I am so eager to learn assembly language. Kindly suggest any book that is suitable for me to learn assembly language. Give some important features of assembly language that can't not be achievable by other high level languages. I am asking this because somebody is telling that you can achieve many things using higher level languages easily why are going for assembly language.

    Thank you once again....

    ---csanthosh---

Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Categories