A 4 digit calculator
using 8086 microprocessor.....
circuit diagram.
Download programs required for various programmable chips from below...
7seg.h
/* 7-seg LED driver routines and defines */
/* Defines To Be Changed According To The Current Schematic
*/
// Comment following line if common cathode (non inverted),
and uncomment if common cathode (inverted).
//#define LED_INVERT 1
// Digits positions
#ifndef LED_SEG_POS_A
#define LED_SEG_POS_A
0
#define LED_SEG_POS_B
1
#define LED_SEG_POS_C
2
#define LED_SEG_POS_D
3
#define LED_SEG_POS_E
4
#define LED_SEG_POS_F
5
#define LED_SEG_POS_G
6
#define LED_SEG_POS_H
7
#endif
/* Non-changeable Defines */
#ifndef LED_INVERT
#define LED_INVERT 0
#endif
#if LED_INVERT
#define LED_OPER &
#define LED_INV
~
#define LED_INIT_VAL
0xFF
#define LED_SEG_VAL(seg_pos)
(0xFF & ~(1 << seg_pos))
#else
#define LED_OPER |
#define LED_INV
#define LED_INIT_VAL
0x00
#define LED_SEG_VAL(seg_pos)
(1 << seg_pos)
#endif
#define LED_SEG_A LED_SEG_VAL(LED_SEG_POS_A)
#define LED_SEG_B LED_SEG_VAL(LED_SEG_POS_B)
#define LED_SEG_C LED_SEG_VAL(LED_SEG_POS_C)
#define LED_SEG_D LED_SEG_VAL(LED_SEG_POS_D)
#define LED_SEG_E LED_SEG_VAL(LED_SEG_POS_E)
#define LED_SEG_F LED_SEG_VAL(LED_SEG_POS_F)
#define LED_SEG_G LED_SEG_VAL(LED_SEG_POS_G)
#define LED_SEG_H LED_SEG_VAL(LED_SEG_POS_H)
/* Output bytes for diffirent numbers */
#define LED_SIGN_0 (LED_INIT_VAL
LED_OPER LED_SEG_A LED_OPER LED_SEG_B LED_OPER LED_SEG_C LED_OPER LED_SEG_D
LED_OPER LED_SEG_E LED_OPER LED_SEG_F)
#define LED_SIGN_1 (LED_INIT_VAL
LED_OPER LED_SEG_B LED_OPER LED_SEG_C)
#define LED_SIGN_2 (LED_INIT_VAL
LED_OPER LED_SEG_A LED_OPER LED_SEG_B LED_OPER LED_SEG_D LED_OPER LED_SEG_E
LED_OPER LED_SEG_G)
#define LED_SIGN_3 (LED_INIT_VAL
LED_OPER LED_SEG_A LED_OPER LED_SEG_B LED_OPER LED_SEG_C LED_OPER LED_SEG_D
LED_OPER LED_SEG_G)
#define LED_SIGN_4 (LED_INIT_VAL
LED_OPER LED_SEG_B LED_OPER LED_SEG_C LED_OPER LED_SEG_F LED_OPER LED_SEG_G)
#define LED_SIGN_5 (LED_INIT_VAL
LED_OPER LED_SEG_A LED_OPER LED_SEG_C LED_OPER LED_SEG_D LED_OPER LED_SEG_F
LED_OPER LED_SEG_G)
#define LED_SIGN_6 (LED_INIT_VAL
LED_OPER LED_SEG_A LED_OPER LED_SEG_C LED_OPER LED_SEG_D LED_OPER LED_SEG_E
LED_OPER LED_SEG_F LED_OPER LED_SEG_G)
#define LED_SIGN_7 (LED_INIT_VAL
LED_OPER LED_SEG_A LED_OPER LED_SEG_B LED_OPER LED_SEG_C)
#define LED_SIGN_8 (LED_INIT_VAL
LED_OPER LED_SEG_A LED_OPER LED_SEG_B LED_OPER LED_SEG_C LED_OPER LED_SEG_D
LED_OPER LED_SEG_E LED_OPER LED_SEG_F LED_OPER LED_SEG_G)
#define LED_SIGN_9 (LED_INIT_VAL
LED_OPER LED_SEG_A LED_OPER LED_SEG_B LED_OPER LED_SEG_C LED_OPER LED_SEG_D
LED_OPER LED_SEG_F LED_OPER LED_SEG_G)
#define LED_SIGN_A (LED_INIT_VAL
LED_OPER LED_SEG_A LED_OPER LED_SEG_B LED_OPER LED_SEG_C LED_OPER LED_SEG_E
LED_OPER LED_SEG_F LED_OPER LED_SEG_G)
#define LED_SIGN_B (LED_INIT_VAL
LED_OPER LED_SEG_C LED_OPER LED_SEG_D LED_OPER LED_SEG_E LED_OPER LED_SEG_F
LED_OPER LED_SEG_G)
#define LED_SIGN_C (LED_INIT_VAL
LED_OPER LED_SEG_A LED_OPER LED_SEG_D LED_OPER LED_SEG_E LED_OPER LED_SEG_F)
#define LED_SIGN_D (LED_INIT_VAL
LED_OPER LED_SEG_B LED_OPER LED_SEG_C LED_OPER LED_SEG_D LED_OPER LED_SEG_E
LED_OPER LED_SEG_G)
#define LED_SIGN_E (LED_INIT_VAL
LED_OPER LED_SEG_A LED_OPER LED_SEG_D LED_OPER LED_SEG_E LED_OPER LED_SEG_F
LED_OPER LED_SEG_G)
#define LED_SIGN_F (LED_INIT_VAL
LED_OPER LED_SEG_A LED_OPER LED_SEG_E LED_OPER LED_SEG_F LED_OPER LED_SEG_G)
/* Encode one digit number into the output byte */
#define LED_ENCODE(value)
\
(value &
0x08)? \
((value &
0x04)? \
((value &
0x02)? \
((value
& 0x01)? \
(LED_SIGN_F): \
(LED_SIGN_E) \
): \
((value
& 0x01)? \
(LED_SIGN_D): \
(LED_SIGN_C) \
) \
): \
((value &
0x02)? \
((value
& 0x01)? \
(LED_SIGN_B): \
(LED_SIGN_A) \
): \
((value
& 0x01)? \
(LED_SIGN_9): \
(LED_SIGN_8) \
) \
) \
): \
((value &
0x04)? \
((value &
0x02)? \
((value
& 0x01)? \
(LED_SIGN_7): \
(LED_SIGN_6) \
): \
((value
& 0x01)? \
(LED_SIGN_5): \
(LED_SIGN_4) \
) \
): \
((value &
0x02)? \
((value
& 0x01)? \
(LED_SIGN_3): \
(LED_SIGN_2) \
): \
((value
& 0x01)? \
(LED_SIGN_1): \
(LED_SIGN_0) \
Board.c
#include "board.h"
#include "7seg.h"
void outp(unsigned int addr, char data)
// Output byte to port
{ __asm
{ mov dx, addr
mov al, data
out dx, al
}
}
char inp(unsigned int addr)
// Input byte from port
{ char result;
__asm
{ mov dx, addr
in al, dx
mov result, al
}
return result;
}
void set_int(unsigned char int_no, void * service_proc)
{ _asm
{ push es
xor ax, ax
mov es, ax
mov al, int_no
xor ah, ah
shl ax, 1
shl ax, 1
mov si, ax
mov ax,
service_proc
mov es:[si], ax
inc si
inc si
mov bx, cs
mov es:[si], bx
pop es
}
}
/* USART */
unsigned char putch_buffer[256];
unsigned char putch_out_pos;
unsigned char putch_pos;
void putch_out(void)
// Output one symbol from buffer to 8251A USART
{ if (putch_out_pos
== putch_pos)
return;
if((inp(ADR_USART_STAT) & 0x01) == 0)
return;
outp(ADR_USART_DATA, putch_buffer[putch_out_pos]);
putch_out_pos++;
}
unsigned char putch( unsigned char c )
// Put one symbol into buffer
{
putch_buffer[putch_pos] = c;
putch_pos++;
return c;
}
void prints(char* s)
// Print string using putch() function
{ char c;
while(s &&
*s)
{ c = *s;
if (c == '\r')
c = '\n';
putch(c);
s++;
}
}
void printui(unsigned int i)
// Print unsigned int using putch() function
{ unsigned char val;
unsigned int temp =
10000;
unsigned char
printed=0;
while (temp >=
1)
{ val = (i / temp) % 10;
if ((val!=0) ||
printed || (temp == 1))
{ putch(val +
'0');
printed = 1;
}
if (temp == 1)
break;
temp /= 10;
}
}
void setup_usart(void)
// 8251 USART Setup
{ /* setup USART */
outp(ADR_USART_CMD,
0x7D); /* ED */
outp(ADR_USART_CMD,
0x07); /* RxEn, TxEn, DTRa */
putch_out_pos = 0;
putch_pos = 0;
}
/* Timer */
signed char delay;
int sound_enabled;
int display_enabled;
void sound_nmi(void)
{ delay++;
if (delay >= 10)
delay =
-delay;
outp(ADR_TIMER_CONTROL, TIMER_COUNTER2 | TIMER_MODE2 | TIMER_LSB);
outp(ADR_TIMER_DATA2, ABS(delay)+0x40);
}
void _interrupt _far nmi_handler(void);
void setup_nmi(void)
// Set NMI Timer at 50Hz.
{ set_int(0x02, (void
*)&nmi_handler);
outp(ADR_TIMER_CONTROL, TIMER_COUNTER1 | TIMER_MODE2 | TIMER_LSB_MSB);
outp(ADR_TIMER_DATA1, 0xD0);
outp(ADR_TIMER_DATA1, 0x07);
}
/* PIO */
// Value to be displayed
unsigned int display_value;
// Current display position
unsigned char cur_display_pos;
// Current dispaly segments
unsigned char cur_display_segs;
unsigned char keys[16];
#define KEY_7 0
#define KEY_8 1
#define KEY_9 2
#define KEY_DIV 3
#define KEY_4 4
#define KEY_5 5
#define KEY_6 6
#define KEY_MUL 7
#define KEY_1 8
#define KEY_2 9
#define KEY_3 10
#define KEY_MIN 11
#define KEY_C 12
#define KEY_0 13
#define KEY_EQ 14
#define KEY_PLU 15
#define KEYBUFFERLEN 16
unsigned char keybuffer[KEYBUFFERLEN];
unsigned char keypos=0;
void process_key(unsigned char keycode)
{ if (keypos <
KEYBUFFERLEN)
{
keybuffer[keypos] = keycode;
keypos++;
}
}
#define NUM_LED_DIGITS 4
unsigned char disp_buffer[4] = {LED_INIT_VAL, LED_INIT_VAL,
LED_INIT_VAL, LED_INIT_VAL};
void display_nmi(void)
// Display And Keyboard Handler
{ unsigned int i;
unsigned int
cur_key;
unsigned int
keys_inp;
unsigned int
out_value;
// Light Off All
Digits
outp(ADR_PPI_PORTA,
0xFF);
// Output Segments
Value
outp(ADR_PPI_PORTB,
cur_display_segs);
// Light On Current
Digit
outp(ADR_PPI_PORTA,
0xFF & ~(1 << cur_display_pos));
// Keyboard Input
keys_inp =
inp(ADR_PPI_PORTC);
cur_key =
(cur_display_pos * 4);
for (i=0; i<4;
i++)
{ if (keys_inp
& (1 << i))
keys[cur_key]=0;
else
{ if
(!keys[cur_key])
{
process_key(cur_key);
keys[cur_key]=1;
}
}
cur_key++;
}
// Shift To The
Next Digit
cur_display_pos++;
if (cur_display_pos
> 3)
{ cur_display_pos
= 0;
}
// Set Next Digit
Value
cur_display_segs =
disp_buffer[cur_display_pos];
}
void init_pio(void)
/* 8255A PIO Demo */
{ outp(ADR_PPI_CONTROL, PPI_PORTA_OUT |
PPI_PORTB_OUT | PPI_PORTCL_INP | PPI_PORTCH_INP | PPI_MODE_BCL_0 |
PPI_MODE_ACH_0 | PPI_ACTIVE);
display_value = 0;
cur_display_pos =
0;
cur_display_segs =
0xFF;
display_enabled =
1;
}
/* NMI Interrupt Handler */
void _interrupt _far nmi_handler(void)
{ if (sound_enabled)
sound_nmi();
if
(display_enabled)
display_nmi();
putch_out();
}
/* Support functions */
void initialise(void)
{ sound_enabled = 0;
display_enabled =
0;
cur_display_segs =
LED_INIT_VAL;
setup_nmi();
setup_usart();
init_pio();
}
char input ()
{ if (keypos > 0)
{ unsigned char
head_key = keybuffer[0];
keypos--;
for (unsigned
char i=0; i<keypos; i++)
keybuffer[i]
= keybuffer[i+1];
switch
(head_key)
{ case KEY_0:
return
'0';
case KEY_1:
return '1';
case KEY_2:
return
'2';
case KEY_3:
return
'3';
case KEY_4:
return
'4';
case KEY_5:
return
'5';
case KEY_6:
return
'6';
case KEY_7:
return
'7';
case KEY_8:
return
'8';
case KEY_9:
return
'9';
case KEY_PLU:
return
'+';
case KEY_MIN:
return
'-';
case KEY_MUL:
return
'*';
case KEY_DIV:
return
'/';
case KEY_EQ:
return
'=';
case KEY_C:
return
'C';
}
}
return 0;
}
char output(char ch)
{ putch(ch);
if (ch >= '0'
&& ch <= '9')
{ for (char i=0; i<NUM_LED_DIGITS-1;
i++)
disp_buffer[i] = disp_buffer[i+1];
disp_buffer[NUM_LED_DIGITS-1] = LED_ENCODE(ch - '0');
}
return ch;
}
void clearscreen()
{ putch(13);
for (char i=0;
i<NUM_LED_DIGITS; i++)
disp_buffer[i] =
LED_INIT_VAL;
}
) \
) \
)
Board.h
#ifndef _board_h_
#define _board_h_
/* 8086 Demo Board support functions and macros */
// Absolute value of an argument
#define ABS(a) ((a>=0)?a:-a)
// Set an Interrupt Handler
void set_int(unsigned char int_no, void * service_proc);
// I/O Ports input and output
void outp(unsigned int addr, char data);
char inp(unsigned int addr);
/* I/O Address Bus decode - every device gets 0x200
addresses */
#define IO0 0x0000
#define IO1 0x0200
#define IO2 0x0400
#define IO3 0x0600
#define IO4 0x0800
#define IO5 0x0A00
#define IO6 0x0C00
#define IO7 0x0E00
#define IO8 0x1000
#define IO9 0x1200
#define IO10 0x1400
#define IO11 0x1600
#define IO12 0x1800
#define IO13 0x1A00
#define IO14 0x1C00
#define IO15 0x1E00
/* 8251A USART */
#define ADR_USART_DATA (IO0 + 0x00)
#define ADR_USART_CMD
(IO0 + 0x02)
#define ADR_USART_STAT ADR_USART_CMD
/* 8253A Timer */
#define ADR_TIMER_CONTROL (IO2 + 0x06)
#define ADR_TIMER_DATA0
(IO2 + 0x00)
#define ADR_TIMER_DATA1
(IO2 + 0x02)
#define ADR_TIMER_DATA2
(IO2 + 0x04)
#define TIMER_COUNTER0 0x00
#define TIMER_COUNTER1 0x40
#define TIMER_COUNTER2 0x80
#define TIMER_LATCH 0x00
#define TIMER_LSB 0x10
#define TIMER_MSB 0x20
#define TIMER_LSB_MSB 0x30
#define TIMER_MODE0 0x00
#define TIMER_MODE1 0x02
#define TIMER_MODE2 0x04
#define TIMER_MODE3 0x06
#define TIMER_MODE4 0x08
#define TIMER_MODE5 0x09
#define TIMER_BCD 0x01
/* 8255A PIO */
#define ADR_PPI_PORTA (IO1)
#define ADR_PPI_PORTB (IO1
+ 0x02)
#define ADR_PPI_PORTC (IO1
+ 0x04)
#define ADR_PPI_CONTROL (IO1
+ 0x06)
#define PPI_PORTA_INP 0x10
#define PPI_PORTA_OUT 0x00
#define PPI_PORTB_INP 0x02
#define PPI_PORTB_OUT 0x00
#define PPI_PORTCL_INP 0x01
#define PPI_PORTCL_OUT 0x00
#define PPI_PORTCH_INP 0x08
#define PPI_PORTCH_OUT 0x00
#define PPI_MODE_BCL_0 0x00
#define PPI_MODE_BCL_1 0x04
#define PPI_MODE_ACH_0 0x00
#define PPI_MODE_ACH_1 0x20
#define PPI_MODE_ACH_2 0x40
#define PPI_ACTIVE 0x80
#endif
Calc.c
/
************
Integer Calculator ( 2K Code Limit) ************
*******************************************************************************/
#include "calc.h"
//Variables
static LONG lvalue;
static LONG rvalue;
static CHAR
currtoken;
static CHAR
lasttoken;
static CHAR
lastpress;
static CHAR
outputbuffer[MAX_DISPLAY_CHAR];
VOID main (VOID)
//Initialise our variables and call the
//Assembly routine to initialise the LCD display.
{ lvalue = 0;
rvalue = 0;
currtoken = '=';
lasttoken = '0';
initialise(); // Initialize the LCD
calc_output(OK);
calc_evaluate();
}
VOID calc_evaluate()
{ CHAR key;
INT i;
CHAR
number[MAX_DISPLAY_CHAR];
CHAR *bufferptr;
// Clear the buffer
before we start.
for (i = 0; i <=
MAX_DISPLAY_CHAR; i++)
{ number[i] = '
';
}
bufferptr =
number;
for (;;)
{ key =
calc_getkey();
if (calc_testkey(key))
// Key test
positive for digit so we read it into the
// buffer and
then write the buffer to the screen/LCD.
// Size limit the number of digits - allow
for termination
// and possible negative results.
{ if
(bufferptr != &number[MAX_DISPLAY_CHAR - 2])
{ *bufferptr
= key;
calc_display(number);
bufferptr++;
}
}
else
// Key is an
operator so pass it to the function handlers.
// If we are
just after startup or cancel then assign to lvalue
// otherwise
assign to rvalue.
{
//Assign the value.
if
(lasttoken == '0')
{
lvalue = calc_asciidec (number);}
else
{
rvalue = calc_asciidec (number);}
//Clear
the number buffer.
bufferptr
= number;
for (i =
0;i <= MAX_DISPLAY_CHAR; i++)
{
number[i] = ' '; }
//Process
the Operator.
currtoken
= key;
if
(currtoken == 'C')
{ calc_opfunctions(currtoken); }
else
{ calc_opfunctions(lasttoken); }
// Clear the outputbuffer for reuse on next
operation.
for (i =
0;i <= MAX_DISPLAY_CHAR;i++)
{
outputbuffer[i] = ' ';}
bufferptr = number;
//
Handle the equals operation here for brevity.
//
All we need do is preserve the previous operator in
//
lasttoken.
if
(currtoken != 0x3D) lasttoken = currtoken;
}
lastpress =
key;
}
}
VOID calc_opfunctions (CHAR token)
// Handle the operations. Lvalue holds the result and we
test for
// consecutive operator presses.
{ CHAR result;
switch(token)
// Add.
{ case '+' : if ((currtoken == '=' ) ||
((lastpress >= 0x30) && (lastpress <=0x39)))
{ lvalue += rvalue;
result = calc_chkerror(lvalue);
}
else
{ result =
SLEEP; } break;
// Subtract.
case
'-' : if ((currtoken == '=' ) || ((lastpress >= 0x30) && (lastpress
<=0x39)))
{ lvalue -= rvalue;
result = calc_chkerror(lvalue);
}
else
{ result = SLEEP;} break;
// Multiply.
case
'*' : if ((currtoken == '=' ) || ((lastpress >= 0x30) && (lastpress
<=0x39)))
{ lvalue *= rvalue;
result = calc_chkerror(lvalue);
}
else
{ result = SLEEP;} break;
//
Divide.
case
'/' : if ((currtoken == '=' ) || ((lastpress >= 0x30) && (lastpress
<=0x39)))
{ if (rvalue)
{ lvalue /= rvalue;
result = calc_chkerror(lvalue);
}
else
{ result = ERROR;}
}
else
{ result = SLEEP;} break;
//
Cancel.
case 'C' : lvalue
= 0;
rvalue = 0;
currtoken = '0';
lasttoken = '0';
result = OK; break;
default
: result = SLEEP;
}
calc_output(result);
}
/************************************************************************
***** Utility Routines *****
***************************/
INT calc_chkerror (LONG num)
// Check upper and lower bounds for the display.
// i.e. 99999999 and -99999999.
{ if ((num >=
-9999999) && (num <= 9999999))
return OK;
else
return ERROR;
}
VOID calc_output (INT status)
// Output according to the status of the operation.
// *Sleep* is used for the first op press after a full
cancel
// or on startup.
{ switch (status)
{ case OK : calc_display(calc_decascii(lvalue)); break;
case
SLEEP : break;
case
ERROR : calc_display("Exception
"); break;
default : calc_display("Exception ");
break;
}
}
LONG calc_asciidec (CHAR *buffer)
// Convert the ASCII string into the floating point number.
{ LONG value;
LONG digit;
value = 0;
while (*buffer != '
')
{ digit =
*buffer - 48;
value = value*10 + digit;
buffer++;
}
return value;
}
CHAR *calc_decascii (LONG num)
// A rather messy function to convert a floating
// point number into an ASCII string.
{ LONG temp = num;
CHAR *arrayptr =
&outputbuffer[MAX_DISPLAY_CHAR];
LONG divisor = 10;
LONG result;
CHAR
remainder,asciival;
INT i;
// If the result of
the calculation is zero
// insert a zero in
the buffer and finish.
if (!temp)
{ *arrayptr =
48;
goto done;
}
// Handle Negative
Numbers.
if (temp < 0)
{
outputbuffer[0] = '-';
temp -= 2*temp;
}
for (i=0 ; i <
sizeof(outputbuffer) ; i++)
{ remainder =
temp % divisor;
result = temp
/ divisor;
//
If we run off the end of the number insert a space into
// the buffer.
if ((!remainder) && (!result))
{ *arrayptr = ' ';}
// We're in business - store the digit
offsetting
// by 48 decimal to account for the ascii
value.
else
{ asciival = remainder + 48;
*arrayptr = asciival;
}
temp
/= 10;
// Save a place for a negative sign.
if (arrayptr != &outputbuffer[1])
arrayptr--;
}
done: return
outputbuffer;
}
CHAR calc_testkey (CHAR key)
// Test whether the key is a digit or an operator. Return 1
for digit, 0 for op.
{ if ((key >=
0x30) && (key <= 0x39))
{ return 1;}
else
{ return 0;}
}
/************************************************************************
***** I/O Routines *****
***********************/
CHAR calc_getkey (VOID)
// Use the input routine from the *Keypad_Read* assembly
file to
// Scan for a key and return ASCII value of the Key pressed.
{ CHAR mykey;
do mykey = input();
while (mykey ==
0);
return mykey;
}
VOID calc_display (CHAR buf[MAX_DISPLAY_CHAR])
// Use the Output and Clearscreen routines from the
// *LCD_Write* assembly file to output ASCII values to the
LCD.
{ INT i = 0;
clearscreen();
for (i = 0 ; i
<= MAX_DISPLAY_CHAR ; i++)
{ if (buf[i] !=
' ')
{ output(buf[i]); }
}
}
/
************ Integer Calculator ( 2K Code Limit)
************
********************************************************************************/
typedef void VOID;
typedef int INT;
typedef unsigned short WORD;
typedef char CHAR;
typedef unsigned char BYTE;
typedef float FLOAT;
typedef double DOUBLE;
typedef long LONG;
// Define the maximum number of ASCII characters that can
fit
// on the display.
#define MAX_DISPLAY_CHAR 9
//Error handling status.
enum ERROR { OK = 0, SLEEP = 1, ERROR = 2};
/************************************************************************
***** FUNCTION PROTOTYPES *****
******************************/
VOID calc_evaluate();
//Operator indirect function.
VOID calc_opfunctions (CHAR token);
//Utility functions.
CHAR
calc_testkey (CHAR ch);
LONG calc_asciidec
(CHAR *buffer);
CHAR *calc_decascii (LONG num);
INT calc_chkerror
(LONG num);
VOID calc_output (INT status);
// I/O functions.
CHAR calc_getkey (VOID);
VOID calc_display (CHAR buf[MAX_DISPLAY_CHAR]);
//Assembly Function prototypes.
void initialise();
char input ();
char output(char ch);
void clearscreen();
Rt.asm
.MODEL SMALL
.8086
.code
extrn _main:proc
.startup
call near ptr _main
endless:
jmp endless
.data
public __acrtused ; trick to force in
startup
__acrtused
= 9876h ; funny value not easily
matched in SYMDEB
.stack