Related articles |
---|
An assembly language for teaching an undergraduate level compiler clas sher@cs.Buffalo.EDUid AA14236; Fri, 1 Sep 89 15:32 (1989-09-01) |
From: | sher@cs.Buffalo.EDU (for compilers) id AA14236; Fri, 1 Sep 89 15:32:51 EDT |
Newsgroups: | comp.compilers |
Date: | 1 Sep 89 19:28:45 GMT |
Original-sender: | ima!harvard!eerie.acsu.buffalo.edu!nobody |
When I found out I was going to teach compilers I decided that probably
the assembly language of the machine they were going to be on was going to
be a problem. Too complex, too little documentation, the possibility of
crashing the machine .... I was looking for an assembly language that
was portable (so I can use it on several machines), simple (so I can focus
on theory) and easily modified (so I could fix mistakes and introduce
complexity if such is needed). This led me to design a
riscy assembly language out of C macros. Any machine with a C compiler could
accept this assembly language so it was portable. It's a simple
register machine with a large (but not enormous) stack and so on.
Because I designed it this way I can monitor how many instructions are
executed and how long they take and so illustrate optimization and other
such concepts. However I can't easily do things like indirect memory
(a la DEC20) or storing the pc (can't get it in C). Since I suspect there
may be some fellow teachers of compilers (intro language processing to be
exact) out there I thought with permission of the moderator I'd post the
thing. Its only 100 odd lines long so net bandwidth won't be overwhelmed.
Here it is:
-David Sher
Ps: I know the stack statements are a bit wierd, every machine has a bit
of wierdness no?
------------------------------cut here------------------------------------
/*
This file contains the macros that translate my pseudo assembly language
into code. This allows me to have a machine independent assembly language
for teaching compilers. Written in 1989 by David Sher,
sher@cs.Buffalo.EDU. Released into the public domain by the author, who
would appreciate it if his name were kept on any copies you make.
*/
#include <stdio.h>
/*
global variables that keep track of how long the program took and
how many instructions were executed
*/
int INSTR_COUNT = 0; /* # of instructions */
int INSTR_TIME = 0; /* time for instructions */
/* ajay :
System-wide constants (different sizes) */
#define WORD (sizeof(int))
#define BYTE (sizeof(char))
/*
definitions of timings
*/
#define MEM_ACCESS 4
#define SIMPLE_OP 1
#define COMPLEX_OP 10
#define STACK_ACCESS 5
#define CONDITIONAL 2
#define IO_CALL 10
/*
Place for registers
*/
int REGS[7];
/*
Place for the stack
*/
int STACK[65535];
int *SP = STACK;
/*
Macros to control the main block
*/
/* begins the main block */
#define BEGIN main(){
/* ends the main block */
#define END printf("\nExecuted %d instructions, took %d units of time\n",INSTR_COUNT,INSTR_TIME); exit(0);}
/*
Macro for static storage allocation , and allocating strings ..
*/
#define BLOCK(NAME,SIZE) int NAME[(SIZE)];
/*
Macros for moving between memory and registers
*/
#define LOAD(R,A) REGS[R] = *(A); INSTR_COUNT++; INSTR_TIME += MEM_ACCESS;
#define LOAD_IMMEDIATE(R,A) REGS[R] = ((int) A); INSTR_COUNT++; INSTR_TIME += MEM_ACCESS;
#define LOAD_INDIRECT(R,R2) REGS[R] = *((int *) REGS[R2]); INSTR_COUNT++; INSTR_TIME += MEM_ACCESS;
#define STORE(R,A) *(A) = REGS[R]; INSTR_COUNT++; INSTR_TIME += MEM_ACCESS;
#define STORE_INDIRECT(R,R2) *((int *) REGS[R2]) = REGS[R]; INSTR_COUNT++; INSTR_TIME += MEM_ACCESS;
/*
Macros for stack manipulation
*/
#define PUSH(R1,R2) ((REGS[R2])? (*(SP - REGS[R2] + 1) = REGS[R1]) : \
(*(++SP) = REGS[R1])); INSTR_COUNT++; INSTR_TIME += STACK_ACCESS;
#define POP(R) REGS[R] = *SP--;INSTR_COUNT++; INSTR_TIME += SIMPLE_OP;
#define GET(R1,R2) REGS[R1] = *(SP - REGS[R2] - 1); INSTR_COUNT++; INSTR_TIME += STACK_ACCESS;
/*
Macros for Arithmetic
*/
#define INC(R) REGS[R]++ ; INSTR_COUNT++ ; INSTR_TIME += SIMPLE_OP ;
#define DEC(R) REGS[R]-- ; INSTR_COUNT++ ; INSTR_TIME += SIMPLE_OP ;
#define ADD(R1,R2,R3) REGS[R3] = REGS[R1] + REGS[R2]; INSTR_COUNT++; INSTR_TIME += SIMPLE_OP;
#define SUBTRACT(R1,R2,R3) REGS[R3] = REGS[R1] - REGS[R2]; INSTR_COUNT++; INSTR_TIME += SIMPLE_OP;
#define MULTIPLY(R1,R2,R3) REGS[R3] = REGS[R1] * REGS[R2]; INSTR_COUNT++; INSTR_TIME += COMPLEX_OP;
#define DIVIDE(R1,R2,R3) REGS[R3] = REGS[R1] / REGS[R2]; INSTR_COUNT++; INSTR_TIME += COMPLEX_OP;
/*
Flow of control statements
*/
#define NOP INSTR_COUNT++; INSTR_TIME += SIMPLE_OP;
#define JUMP(L) INSTR_COUNT++; INSTR_TIME += SIMPLE_OP;goto L;
#define JUMP_ZERO(R,L) INSTR_COUNT++; INSTR_TIME += CONDITIONAL;if( REGS[R] == 0 ) goto L;
#define JUMP_NEGATIVE(R,L) INSTR_COUNT++; INSTR_TIME += CONDITIONAL;if( REGS[R] < 0 ) goto L;
#define JUMP_POSITIVE(R,L) INSTR_COUNT++; INSTR_TIME += CONDITIONAL;if( REGS[R] > 0 ) goto L;
/*
SUBROUTINE management
*/
#define BEGIN_PROCEEDURE(NAME) void NAME(){
#define END_PROCEEDURE }
#define CALL(NAME) NAME(); INSTR_COUNT++; INSTR_TIME += STACK_ACCESS;
/*
I/O management
*/
#define READ(R) REGS[R] = (int) getchar(); INSTR_COUNT++; INSTR_TIME += IO_CALL;
#define WRITE(R) (void) putchar((char) REGS[R]); INSTR_COUNT++; INSTR_TIME += IO_CALL;
/* debugging help ... */
#define DUMP printf("Register Dump :- \n"); printf(" R0 R1 R2 R3 R4 R5 R6\n"); printf("%7x %7x %7x %7x %7x %7x %7x\n\n",REGS[0],REGS[1],REGS[2],REGS[3],REGS[4],REGS[5],REGS[6]);
-David Sher
ARPA: sher@cs.buffalo.edu BITNET: sher@sunybcs
UUCP: {rutgers,ames,boulder,decvax}!sunybcs!sher
[From sher@cs.Buffalo.EDU]
Return to the
comp.compilers page.
Search the
comp.compilers archives again.