• C

interrupt question - reopen for segelebel

segelebel and others,
With reference to the last question on altering timer interrupt vector , I want to know what I should do if the program is set up to involve real time calculations. I tried to add ctime and time in the interrupt handler. But the program just crashed and chucked me back to windows...

To make this clear, I just give you an example for what I've done...

/*
    Interrupt 1Ch - redirection to display        the count of interruption
    done by this ISR.
*/

#include <dos.h>
#include <time.h>

void    interrupt       new_1C      ();
void    interrupt       (*old_1C)   ();
void    write_string    (int x, int y, char *p, int attr);
void    set_vid_mem     (void);

unsigned    paragraphs;
int         count;
char        far *vid_mem;
char        str[5];
time_t      llongtime;
char        *v2;

main() {

    set_vid_mem ();

    old_1C = getvect (0x1C);
    setvect (0x1C, new_1C);
    paragraphs = (_SS + (_SP >> 4) + 1) - _psp;
    keep(0, paragraphs);

}

/* low level functions */


/*  Get the current video mode
*/

video_mode (void)
{
    union REGS r;

    r.h.ah = 15;
    return int86 (0x10, &r, &r) & 255;
}

/*  Set pointer to video memory
*/
void    set_vid_mem (void)
{
    int vmode;

    vmode = video_mode ();
    if ((vmode != 2) && (vmode != 3) && (vmode != 7)) {
        printf ("video must be in 80 column text mode\n");
        exit (1);
    }

    if (vmode == 7)
        vid_mem = (char far *) MK_FP (0xB000, 0);
    else
        vid_mem = (char far *) MK_FP (0xB800, 0);
}

/*  Write a string to video memory
*/
void    write_string (int x, int y, char *p, int attr)
{
    char far *v;

    v = vid_mem;
    v += (y*160) + x*2;
    for (; *p; ) {
        *v++ = *p++;
        *v++ = attr;
    }
}


/*
    new Int 1C Service routine.
*/

void interrupt new_1C ()
{
    (old_1C)();
    disable ();
    itoa(++count, str, 10);
    write_string (76, 0, str, 31);
    time(&llongtime);  <---------|
    v2 = ctime(&llongtime);<-----|--added

    write_string(0,0,v2, 31);<---|
   
    enable ();
}

 






Thanks
Jacky
whlukAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

whlukAuthor Commented:
Edited text of question.
0
SteveGTRCommented:
I believe that your problem occurs because the time() or ctime() functions resolves to calls to DOS (int 21). If you call a DOS interrupt when one is already processing your code goes boom! This link provides you with information about DOS reentrancy problems (and others) and how to overcome them.

http://www.ece.uiuc.edu/ece291/books/CH18/CH18-3.html

Good Luck,
Steve
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
whlukAuthor Commented:
So What I am to do?
0
SteveGTRCommented:
The text says:

"MS-DOS provides a special one-byte flag (InDOS) that contains a zero if DOS is currently active and a non-zero value if DOS is already processing an application request. By testing the InDOS flag your TSR can determine if it can safely make a DOS call. If this flag is zero, you can always make the DOS call. If this flag contains one, uou may not be able to make the DOS call. MS-DOS provides a function call, Get InDOS Flag Address, that returns the address of the InDOS flag. To use this function, load ah with 34h and call DOS. DOS will return the address of the InDOS flag in es:bx. If you save this address, your resident programs will be able to test the InDOS flag to see if DOS is active."

So you should perform the following steps:

1) Create a pointer for InDOS flag
2) Capture address of InDOS flag when initializing TSR
3) Test InDOS flag prior to calling DOS functions

This leads to the question, "What do I do if DOS is busy?". In your case I'd just skip the time stuff and just add to counter.

So here some code:

/* Creation of global InDOS flag */

char far *pInDOS;

/* Initialization of InDOS flag, can be in main() */

  union REGS regs;
  struct SREGS segs;

  r.h.ah = 0x34h;

  int86x(0x21, &regs, &regs, &segs);
      
  pInDOS = (char far *) MK_FP(segs.es, regs.x.bx);

/* Testing inDOS flags */

void interrupt new_1C ()
{
  (old_1C)();
  disable ();
  itoa(++count, str, 10);
  write_string (76, 0, str, 31);

  if (*pInDOS == 0)
    {
    time(&llongtime);  
    v2 = ctime(&llongtime);

    write_string(0, 0, v2, 31);
    }    

  enable ();
}

I hope this helps.

Steve
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C

From novice to tech pro — start learning today.