Sunday 13 November 2011

How can I access important DOS memory locations from my program? in C programming

How can I access important DOS memory locations from my program?

Like the DOS and BIOS functions, there are dozens of memory locations that contain useful and interesting information about the computer. Need to know the current display mode without using an interrupt? It’s in 40:49 hex (that’s segment 40, offset 49). Want to find out whether the user is currently pressing the Shift, Ctrl, or Alt keys? That information is in 40:17. Want to write directly to the screen? Monochrome screens start at 0xB000:0, color text mode and 16-color graphics modes (below 640´480 16 colors) start at 0xB800:0, and all other standard graphics modes (including 640´480 16 colors and up) start at 0xA000:0. Refer to FAQ XIV.8 for more information. The following example shows how to print color text mode characters to the screen. Note that this is a slight modification to the example used in the previous few questions.

#include <stdlib.h>
#include <dos.h>
char GetAKey(void);
void OutputString(int,int,unsigned int,char *);
main(int argc, char ** argv)
{
char str[128];
union REGS regs;
int ch, tmp;
/* copy argument string; if none, use “Hello World” */
strcpy(str, (argv[1] == NULL ? “Hello World” : argv[1]));
/* print the string in red at top of screen */
for(tmp=0;((ch = GetAKey()) != 27); tmp+=strlen(str)){
OutputString(0,tmp,0x400,str);
}
}
char
GetAKey()
{
union REGS regs;
regs.h.ah = 0; /* get character */
int86(0x16, &regs, &regs);
return((char)regs.h.al);
}
void
OutputString(int row, int col, unsigned int videoAttribute, char *outStr)
{
unsigned short far * videoPtr;
videoPtr = (unsigned short far *)(0xB800L << 16);
videoPtr += (row * 80) + col; /* Move videoPtr to cursor position */
videoAttribute &= 0xFF00; /* Ensure integrity of attribute */
/* print string to RAM */
while(*outStr != ‘\0’){
/* If newline was sent, move pointer to next line, column 0 */
if( (*outStr == ‘\n’) || (*outStr == ‘\r’) ){
videoPtr += (80 - ( ((int)FP_OFF(videoPtr) / 2) % 80));
outStr++;
continue;
}
/* If backspace was requested, go back one */
if(*outStr == 8){
videoPtr--;
outStr++;
continue;
}
/* If BELL was requested, don’t beep, just print a blank
and go on */
if(*outStr == 7){
videoPtr++;
outStr++;
continue;
}
/* If TAB was requested, give it eight spaces */
if(*outStr == 9){
*videoPtr++ = videoAttribute | ‘ ‘;
*videoPtr++ = videoAttribute | ‘ ‘;
*videoPtr++ = videoAttribute | ‘ ‘;
*videoPtr++ = videoAttribute | ‘ ‘;
*videoPtr++ = videoAttribute | ‘ ‘;
*videoPtr++ = videoAttribute | ‘ ‘;
*videoPtr++ = videoAttribute | ‘ ‘;
*videoPtr++ = videoAttribute | ‘ ‘;
outStr++;
continue;
}
/* If it was a regular character, print it */
*videoPtr = videoAttribute | (unsigned char)*outStr;
videoPtr++;
outStr++;
}
return;
}

Obviously, printing text characters to the screen is a bit more complicated when you have to do it yourself. I even made shortcuts by ignoring the meaning of the BELL character (to issue a beep) and a couple of other special characters (although I did implement carriage return and linefeed). Regardless, this function performs basically the same task as the previous examples, except that now you have control over the color of the character and its position when printed. This example starts printing from the top of the screen. If you want more examples of using memory locations, refer to FAQs XX.1, XX.12, and XX.17—these all use pointers to low DOS memory to find useful information about the computer.

Cross Reference:

XIV.5: What is BIOS?
XX.1: How are command-line parameters obtained?
XX.12: How can I pass data from one program to another?
XX.17: Can you disable warm boots (Ctrl-Alt-Delete)?

No comments:

Post a Comment