home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
mass61.zip
/
mass.zip
/
masm61
/
DISK3
/
SAMPLES
/
DEMOS
/
MATHDEMO.C$
/
MATHDEMO
Wrap
Text File
|
1992-11-12
|
15KB
|
387 lines
/* MATHDEMO.C - Creates a simple on-screen calculator with functions for
* basic integer arithmetic and for solving for the roots of a quadratic
* equation. MATHDEMO invokes procedures that illustrate assembly-language
* instructions related to mathematics, including those specific to the
* 8087 family of coprocessors.
*
* MATHDEMO.EXE is built from the following files:
* MATHDEMO.C - Main program
* MATH.ASM - Assembly procedures for MATHDEMO
* COMMON.ASM - Assembly procedures shared by other example programs
* DEMO.INC - Assembly include file with macros and structure declarations
* DEMO.H - C include file with prototypes and structure declarations
*
* Procedures: AddLong MulLong DivLong Quadratic
* SubLong ImulLong IdivLong
*/
#include "demo.h"
#include <dos.h>
#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
/* Function prototypes */
void display_calc( void );
void display_help( void );
void press( void );
void push( int sign );
/* Global variables */
long s1, s2, s3; /* Stack values: 1st, 2nd, 3rd */
char entry[11]; /* Entry window string */
int col; /* Current display column for entry */
main()
{
int ch, err; /* Keyboard character, return val */
static int sign, mode; /* Sign flag, signed/unsigned flag */
static float root1, root2; /* Roots of quadratic equation */
static short quotient, remainder; /* Results of division */
static long *product, result;
static char *rmsg[2] = { "Complex", "roots" };
static char *dmsg[2] = { "Division by", "Zero" };
static char *highmsg = { "high:" };
static char *lowmsg = { "low:" };
GetVidConfig();
display_calc();
StrWrite( 9, 14, "+" );
col = 20;
do
{
SetCurPos( 9, col );
ch = getch();
switch( (ch = toupper( ch )) )
{
/* Display number in entry window. */
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
putch( (char) ch );
entry[col - 20] = (char) ch;
entry[++col - 20] = 0;
if( col == 30 )
col--;
break;
/* Toggle between signed and unsigned arithmetic modes. */
case 'M':
if( mode )
{
mode = 0; /* For signed mode, */
StrWrite( 14, 57, " (" ); /* toggle flag off */
StrWrite( 9, 14, "+" ); /* and restore sign */
}
else
{
mode++; /* For unsigned mode, */
StrWrite( 14, 57, "(un" ); /* toggle flag on */
StrWrite( 9, 14, " " ); /* and blank sign */
}
sign = 0;
break;
/* Solve for x in quadratic equation s3*x*x + s2*x + s3 = 0. */
case 'Q':
push( sign );
err = Quadratic( (float)s3, (float)s2, (float)s1,
&root1, &root2 );
ClearBox( 7, 9, 15, 9, 29 ); /* Clear entry window */
ClearBox( 7, 9, 49, 10, 66 ); /* Clear result window */
if( err < 2 )
{
SetCurPos( 9, 50 );
printf( "%16.3f", root1 ); /* Display 1st root */
if( !err )
{
SetCurPos( 10, 50 );
printf( "%16.3f", root2 ); /* Display 2nd root */
}
}
if( err == 2)
{
StrWrite( 9, 50, rmsg[0] ); /* Display "Complex */
StrWrite( 10, 50, rmsg[1] ); /* roots" */
}
break;
/* Change sign. */
case 'S':
if( !mode ) /* Allow sign changes only */
{ /* in signed mode */
if( sign )
{
StrWrite( 9, 14, "+" );
sign = 0;
}
else
{
StrWrite( 9, 14, "-" );
sign++;
}
}
break;
/* Clear stack, reinitialize variables. */
case 'C':
s3 = s2 = s1 = 0;
ClearBox( 7, 9, 15, 9, 29 ); /* Clear entry window */
ClearBox( 7, 9, 49, 10, 66 ); /* Clear result window */
entry[0] = 0;
col = 20;
break;
/* Push values down stack when ENTER key pressed. */
case CR:
push( sign );
break;
/* Display help screen. */
case '?':
case 'H':
display_help(); /* Display help */
display_calc(); /* Redisplay calculator */
StrWrite( 9, 20, entry ); /* and entry number */
if( mode )
{
StrWrite( 14, 57, "(un" ); /* Make "unsigned" */
StrWrite( 9, 14, " " ); /* and blank sign */
}
else
{
if( sign )
StrWrite( 9, 14, "-" );
else
StrWrite( 9, 14, "+" );
}
break;
/* Add or subtract s1 and s2. */
case '+':
case '-':
push( sign );
if( (char) ch == '+' )
s1 = AddLong( s2, s1 );
else
s1 = SubLong( s2, s1 );
ClearBox( 7, 9, 15, 9, 29 ); /* Clear entry window */
ClearBox( 7, 9, 49, 10, 66 ); /* Clear result window */
SetCurPos( 9, 56 );
if( mode )
printf( "%lu", s1 ); /* Display unsigned or */
else
printf( "%li", s1 ); /* signed result */
break;
/* Multiply s1 and s2. */
case '*':
push( sign );
if( mode )
product = MulLong( s2, s1 );
else
s1 = ImulLong( s2, s1 );
ClearBox( 7, 9, 15, 9, 29 ); /* Clear entry window */
ClearBox( 7, 9, 49, 10, 66 ); /* Clear result window */
if( mode )
{
StrWrite( 9, 50, highmsg );
StrWrite( 10, 50, lowmsg );
SetCurPos( 9, 56 );
printf( "%lu", *++product ); /* Display high and low */
SetCurPos( 10, 56 ); /* double-word of */
printf( "%lu", *--product ); /* unsigned product */
s1 = *product; /* Copy low word to stack */
}
else
{
SetCurPos( 9, 56 );
printf( "%li", s1 ); /* Display signed product */
}
break;
/* Divide s2 by s1. */
case '/':
push( sign );
if ( s1 == 0 )
{
StrWrite( 9, 50, dmsg[0] ); /* Display "Division by */
StrWrite( 10, 50, dmsg[1] ); /* zero" */
}
else
{
if( mode )
quotient = DivLong( s2, (int) s1, &remainder );
else
quotient = IdivLong( s2, (int) s1, &remainder );
ClearBox( 7, 9, 15, 9, 29 ); /* Clear entry */
ClearBox( 7, 9, 49, 10, 66 ); /* Clear result */
if( abs( (int) remainder ) >= (abs( (int) s1 ) >> 1) )
{
if( quotient >= 0 ) /* Round up if */
quotient++; /* remainder > s1/2 */
else
quotient--;
}
SetCurPos( 9, 56 );
if( mode )
printf( "%u", quotient ); /* Display result */
else
printf( "%i", quotient );
s1 = (long) quotient; /* Copy quotient to stack */
}
break;
}
} while( ch != ESCAPE );
clear_scrn( 7, 0, 24 ); /* Clear screen before exit */
SetCurPos( 23, 0 ); /* and set cursor to bottom */
return( 0 );
}
/* display_calc - Clears screen and displays calculator.
*
* Params: None
*/
void display_calc( void )
{
static char *calculator[19] =
{
" *** MATH Demonstration Program ***",
"",
"",
"┌─ Integer Calculator ───────────────────────────────────────────────────┐",
"│ │",
"│ ┌────────────────┐ ┌──────────────────┐ │",
"│ │ │ │ │ │",
"│ └────────────────┘ │ │ │",
"│ entry └──────────────────┘ │",
"│ result │",
"│ 7 8 9 + - ? = Help │",
"│ M = Mode (signed) │",
"│ 4 5 6 * / S = Change sign │",
"│ Q = Solve quadratic │",
"│ 1 2 3 ─┘ Enter C = Clear all │",
"│ │",
"│ 0 Esc = Quit │",
"│ │",
"└────────────────────────────────────────────────────────────────────────┘"
};
int i;
clear_scrn( 7, 0, 24 );
if( vconfig.display )
ClearBox( 31, 6, 2, 21, 77 );
else
ClearBox( 15, 6, 2, 21, 77 );
ClearBox( 7, 9, 14, 9, 29 ); /* Clear entry window */
ClearBox( 7, 9, 49, 10, 66 ); /* Clear result window */
for( i = 0; i < 19; i++) /* Display calculator */
StrWrite( i + 3, 3, calculator[i] );
}
/* display_help - Clears screen and displays help text.
*
* Params: None
*/
void display_help( void )
{
static char *help_msg[24] =
{
"The Integer Calculator works somewhat like an RPN hand "
"calculator. Type the", "first integer, press Enter (─┘), type the "
"second integer, and press the", "desired operator key. The answer "
"appears in the result window.",
"",
"To keep things simple, the Integer Calculator handles only long or "
"short", "integers -- no floating point numbers allowed. Unsigned "
"numbers can range", "from 0 to 4,294,967,295; signed numbers from "
"-2,147,483,648 to 2,147,483,647.", "There's one exception to "
"this: when dividing two numbers, the divisor must", "be a short "
"integer from 0 to 65,535 for unsigned division, or from -32,768",
"to 32,767 for signed division.",
"",
"Press the M key to toggle between signed and unsigned arithmetic. " \
"Press the", "S key to change the sign of the number in the entry "
"window. You'll notice", "the Calculator allows a change of sign "
"only in \"signed\" mode.",
"",
"The Calculator uses coprocessor instructions (either real or "
"simulated) to", "solve for the roots of a quadratic equation in "
"the form",
"",
" A*x*x + B*x + C = 0",
"",
"Enter the three equation constants A, B, and C in order, then "
"press Q. The", "roots, if they exist, appear in the result "
"window. If the equation has only", "one root, then only a single "
"number is displayed. For example, try entering", "3, 7, and 2 "
"for A, B, and C."
};
int i;
clear_scrn( 7, 0, 24 );
for( i = 0; i < 24; i++)
StrWrite( i, 0, help_msg[i] );
press();
}
/* push - Pushes values down one stack position: s3 becomes s2,
* s2 becomes s1, and s1 becomes the value in the entry window.
*
* Params: sign - Current sign status (0 = positive, 1 = negative)
*/
void push( int sign )
{
unsigned long place;
s3 = s2;
s2 = s1;
s1 = 0;
place = 1;
if( entry[col - 20] )
{
s1 = (long) (entry[col - 20] - '0');
place = 10;
}
while( col > 20 )
{
s1 += place * (long) (entry[--col - 20] - '0');
place *= 10;
}
if( sign )
s1 = -s1;
ClearBox( 7, 9, 15, 9, 29 ); /* Clear entry window */
entry[0] = 0; /* Reinitialize entry string */
col = 20; /* Reset column count */
}
/* press - Prompt for keyboard signal to continue.
*
* Params: None
*/
void press( void )
{
SetCurPos( 24, 49 );
printf( ". . . press a key to continue" );
SetCurPos( 24, 47 );
getch();
}