Modified intlib to use system vars intacc, intarg, and intovr

This commit is contained in:
Curtis F Kaylor 2022-04-04 19:47:16 -04:00
parent 8495b43011
commit a220bd0592
7 changed files with 729 additions and 327 deletions

224
a02.c
View File

@ -1,7 +1,6 @@
/* Simple 6502 Assembler *
* for C02 Compiler *
* Uses DASM Syntax but *
* supports 65C02 Op Codes */
/* 6502 Assembler for C02 Compiler *
* Uses DASM Syntax but supports *
* 65C02 and Sweet 16 Opcodes */
#include <stdio.h>
#include <stdlib.h>
@ -15,13 +14,23 @@ int debug; //Ouput Debug Info
#define INCLEN 255
char incpath[INCLEN];
enum otypes {BINFIL, PRGFIL}; //Object File Types
enum otypes {BINFIL, APLFIL, ATRFIL, INTFIL, MSRFIL, PRGFIL}; //Object File Types
int obin[] = {TRUE, FALSE, TRUE, FALSE, FALSE, TRUE}; //Is File Type Binary
int olen[] = {0, 8, 32, 0, 0}; //Hex Bytes per Line
char objtyp; //Object File Type
int objbin; //Binary Object File Flag
int objlen; //Text Object File Line Length
int objcnt; //Text Object File Byte Count
int chksum; //Text Object File Checksum
int orgadr; //Origin Address
int curadr; //Current Address
int endadr; //Address after Last Byte
int exeadr; //Execution Start Address
int lstadr; //List Address
char hdrtxt[MAXSTR]; //SREC Header Record Text
struct sym {int block; char name[MAXLBL+1]; int bytes, value, refrd;};
struct sym symbol; //Current Symbol
struct sym symtbl[MAXSYM]; //Global Symbol Table
@ -36,6 +45,7 @@ char cmmnt[MAXSTR]; //Assembly Line Comment
char mcode[MAXSTR]; //Generated Bytes
char strng[MAXSTR]; //Parsed String
int opridx; //Index into Operand
char cpdchr; //Last Character Copied into oprnd
@ -67,8 +77,13 @@ FILE *incfil; //Include File Pointer
/* Print Usage Info and Exit */
void usage(char* appnam) {
printf("Usage: %s [opts] asmfile objfile [lstfile]\n", appnam);
printf(" Opts: -p - Commodore PRG format\n");
printf(" -d - Output Debug Info\n");
printf(" Opts: -d - Output debug info\n");
printf(" -h - SREC header record text\n");
printf(" -a - Apple-1 monitor format\n");
printf(" -p - Commodore PRG format\n");
printf(" -s - Motorola SREC format\n");
printf(" -x - Intel HEX format");
printf(" \n");
exit(EXIT_FAILURE);
}
@ -105,15 +120,18 @@ void xerror(char* format, char *s) {
/* Open File with Error Checking */
FILE * opnfil(char* name, char* mode, char* path) {
if (debug) printf("Opening file '%s' with mode '%s'\n", name, mode);
if (debug && strlen(path)) printf("using path list '%s'\n", path);
FILE *fp = fopen(name, mode);
if (!fp) {
char spec[256];
char *token = strtok(path, " ");
while (token) {
strcpy(spec, path); strcat(spec, "\\"); strcat(spec, name);
char spec[256], paths[256];
strcpy(paths, path);
char *token = strtok(paths, " ");
while (token != NULL) {
strcpy(spec, token); strcat(spec, "\\"); strcat(spec, name);
if (debug) printf("Opening file \"%s\" with mode \"%s\"\n", spec, mode);
fp = fopen(spec, mode); if (fp) break;
token = strtok(NULL, " ");
if (debug) printf("token = \"%s\"\n", token);
}
}
if (!fp) xerror("Error Opening File '%s'\n", name);
@ -121,6 +139,17 @@ FILE * opnfil(char* name, char* mode, char* path) {
return fp;
}
/* Open Object FIle */
FILE * opnobj(char* objnam, char* path) {
char mode[3] = "w";
objbin = obin[objtyp];
if (debug) printf("Set objbin to %d\n", objbin);
objlen = olen[objtyp];
if (debug) printf("Set objlen to %d\n", objlen);
if (objbin) strcat(mode, "b");
return opnfil(objnam, mode, path);
}
/* Skip Character in Input Line *
* Args: c - Character to Skip *
* Updates: linptr */
@ -205,11 +234,16 @@ int plabel(void) {
return found;
}
/* Append to Operand */
void aoprnd(int c) {
if (opridx < MAXSTR) oprnd[opridx++] = toupper(c);
}
/* Copy Character to Operand and Increment */
int cpychr(int c) {
if (c && toupper(*linptr) != c) return FALSE;
cpdchr = *linptr;
if (opridx < MAXSTR) oprnd[opridx++] = toupper(cpdchr);
aoprnd(cpdchr);
linptr++;
return TRUE;
}
@ -324,11 +358,66 @@ int evlopd(int maxsiz) {
return result;
}
/* Write Hex and Update Checksum */
void outhex(char prefix, int b) {
if (prefix) fputc(prefix, outfil);
fprintf(outfil, "%02X", b);
chksum += b;
} \
/* Write Hex Address */
void outadr(int w) {
outhex(0, w >> 8);
outhex(0, w & 0xFF);
}
/* Write Hex File Line Header */
void outhdr(int addr) {
chksum = 0;
int linlen = __min(objlen, endadr - curadr + 1);
if (debug) printf("outhdr: curadr=%04x, endadr=%04x, linlen=%04x\n", curadr, endadr, linlen);
switch (objtyp) {
case INTFIL: outhex(':', linlen); outadr(addr); outhex(0, 0); break;
default: outadr(addr); //Write Address
}
if (objtyp == APLFIL) fputc(':', outfil);
}
/* Write Checksum */
void outchk(void) {
if (objtyp == INTFIL) outhex(0, -chksum & 0xFF);
}
/* Write Hex File Line End */
void outend(void) {
if (objtyp = INTFIL) outchk(); //Write Checksum
fputs("\n", outfil);
objcnt = 0;
}
/* Write Hex File End of File */
void outeot(void) {
if (objcnt) outend();
if (objtyp = INTFIL); fputs(":00000001FF\n", outfil);
}
/* Write Byte to Hex Object File */
void outtxt(int b) {
if (objcnt == 0) outhdr(curadr - 1);
switch (objtyp) {
case APLFIL: outhex(' ', b); break;
default: outhex(0, b);
}
objcnt++;
if (objcnt == objlen) outend();
}
/* Write Byte to Output File */
void outbyt(int b) {
if (curadr > -1) curadr++;
if (passno != 2) return;
fputc(b & 0xFF, outfil);
if (objbin) fputc(b & 0xFF, outfil);
else outtxt(b);
sprintf(bytstr, "%02X ", b);
if (strlen(mcode) < 9) strcat(mcode, bytstr);
}
@ -339,6 +428,20 @@ void outwrd(int w) {
outbyt(w >> 8);
}
/* Write Atari 8-Bit EXE Block Header */
void atrhdr(int saddr, int eaddr) {
outwrd(0xFFFF); //Binary File Indicator
outwrd(saddr); //Start Address
outwrd(eaddr-1); //End Address
}
/* Write Atari 8-Bit EXE Ending Block */
void atrend(void) {
atrhdr(0x02E0, 0x02E2);
outbyt(0x4C); //JMP
outwrd(exeadr); //start address
}
/* Lookup Opcode */
int lkpopc(struct opc opl[]) {
if (debug) printf("Looking up Mnemonic %s\n", mnmnc);
@ -403,15 +506,23 @@ void asmequ(void) {
setsym(evlopd(0xFFFF), 0);
}
/* Assemble EXE Pseudo-Op */
void asmexe(void) {
exeadr = evlopd(0xFFFF);
}
/* Assemble ORG Pseudo-Op */
void asmorg(void) {
orgadr = evlopd(0xFFFF);
if (exeadr < 0) exeadr = orgadr;
if (passno == 1 && symbol.name[0]) {
symbol.value = orgadr;
symbol.bytes = 2;
}
if (passno == 2 && objtyp == PRGFIL)
outwrd(orgadr);
if (passno == 2 ) {
if (objtyp == PRGFIL) outwrd(orgadr);
if (objtyp == ATRFIL) atrhdr(orgadr, lstadr);
}
curadr = orgadr;
lstadr = orgadr;
}
@ -473,6 +584,7 @@ int asmpso(int dot) {
case 'M': asmens(); break; //ENDSubroutine
case 'I': asminf(); break; //INCLude
case '*': asmorg(); break; //ORG
case 'X': asmexe(); break; //EXEC
case 'P': asmprc(); break; //PROCessor
case 'E': asmend(); break; //END
case 'A': asmaln(); break; //ALIGn
@ -607,17 +719,76 @@ void dbgopc(void) {
}
}
/* Evaluate Register Operand *
* Returns: Register Number 0-15 */
int evlreg(void) {
char name[MAXSTR];
int result;
if (debug) puts("Evaluating Register Argument");
int rel = cpychr('@');
if (debug) printf("Set rel to %d\n", rel);
if (amode == INDCT && !rel) xerror("Indirect Argument Required\n", "");
if (amode == RGIND && rel) token = token + 0x20; //LD or ST relative
char pfx = 'R'; if (!cpychr(pfx)) pfx = 0;
if (debug) puts("Evaulating Register Number");
if (pfx && isalpha(*linptr)) return evlhex(0x0F);
if (isdigit(*linptr)) return evldec(0x0F);
if (!pword(FALSE, name)) xerror("Register Argument Required\n", "");
for (int i=0; name[i]; i++) if (opridx<MAXSTR) oprnd[opridx++] = name[i];
if (pfx) pfxstr(pfx, name);
if (debug) printf("Parsed Register Name %s \n", name);
if (strcmp(name, "ACC")==0) return 0; //Accumulator (R0)
if (strcmp(name, "PR")==0) return 14; //Prior Result (R14)
if (strcmp(name, "PC")==0) return 15; //Accumulator (R0)
xerror("Illegal Register %s\n", name);
}
/* Assemnble Register Instruction */
void asmreg(void){
if (debug) printf("Assembling Register Opcode %02x\n", token);
int regno = evlreg();
if (debug) printf("Register Number: %d\n", regno);
token = token | regno;
if (amode == ABSLT) {
if (debug) puts("Evaluating Absolure Argument");
skpspc();
if (!cpychr(',')) aoprnd(' '); //Skip optional comma
opval = evlopd(0xFFFF);
if (opval < 0) xerror("Absolute Argument Required\n", "");
}
}
/* Assemble Sweet 16 Opcode */
int asmswo(void) {
opval = -1;
if (lkpopc(swolst) == FALSE) return FALSE;
if (debug) printf("Assembling Sweet 16 Instruction %s, ", mnmnc);
if (debug) printf("Addressing Mode 0x%04X\n", amode);
skpspc();
switch (amode) {
case IMPLD: break; //Implied Instruction
case RELTV: asmbrn(TRUE); break; //Branch (Relative) Instruction
default: asmreg(); //Assemble Register Instruction
}
if (debug) printf("Writing OpCode $%02X\n", token);
outbyt(token);
if (debug) printf("Writing %s Operand %d\n", zpgabs[-zpage], opval);
if (opval >= 0) {if (amode == RELTV) outbyt(opval); else outwrd(opval);}
return TRUE;
}
/* Assemble Opcode */
int asmopc(int dot) {
opmod = 0;
if (asmpso(dot)) return TRUE; //Check For/Assemble Pseudo-Op
if (asmswo()) return TRUE; //Check for/Assemble Sweet-16 Instruction
if (lkpopc(opclst) == FALSE) xerror("Invalid Mnemonic %s\n", mnmnc);
if (debug) printf("Assembling Opcode Token 0x%02X, ", token);
if (debug) printf("Addressing Mode Mask 0x%04X\n", amode);
skpspc();
if (amode == RELTV) asmbrn(TRUE); //Branch (Relative) Instruction
else if (amode == 0x0004 || amode == 0x1004) asmzpr(); //Branch (Relative) Instruction
else if (cpychr('#')) asmimd(); //Assemble Implied Instruction
else if (amode == 0x0004 || amode == 0x1004) asmzpr(); //Branch ZP (Relative)
else if (cpychr('#')) asmimd(); //Assemble Immediate Instruction
else if (cpychr('(')) asmind(); //Assemble Indirect Instruction
else asmiaz(); //Assemble Implied/Accumulator/Absolute/ZeroPage Instruction
if (debug) dbgopc();
@ -685,6 +856,13 @@ void clsinc(void) {
endasm = FALSE; //Clear End Flag for Return to Main File
}
/* Close Object File */
void clsobj() {
if (objbin) {if (objtyp == ATRFIL) atrend();}
else {if (objcnt) outeot();}
fclose(outfil);
}
/* Assemble Input File (Two Pass) *
* Args: pass - Assembly Pass (1 or 2) *
* Requires: inpfil - Input File Pointer *
@ -699,6 +877,8 @@ void asmfil(int pass) {
blknum = 0; // and Local Block Number
orgadr = -1; //Origin Address Not Set
curadr = orgadr; //Set Current Address to Origin
exeadr = -1; //Execution Address Not Set
objcnt = 0; //Initialize Object File Byte Count
if (debug) printf("Rewinding Input File\n");
rewind(inpfil); //Start at Beginning of Input File
while (TRUE) {
@ -720,6 +900,8 @@ void asmfil(int pass) {
lineno++;
if (incnam[0] && incfil == NULL) opninc(); //Open Include File
}
endadr = curadr; //Set End Address for Second Pass
if (debug) printf("End address set to %04x\n", endadr);
}
/* Parse Command Line Option */
@ -729,9 +911,14 @@ int pcoptn(char *argval) {
if (debug) printf(" Option '%c'\n", option);
switch(option) {
case 'D': debug = TRUE; break; //Enable debug Output
case 'A': objtyp = APLFIL; break; //Apple-1 Monitor Entry File
case 'E': objtyp = ATRFIL; break; //Atari 8-Bit EXE File
case 'P': objtyp = PRGFIL; break; //Commodore PRG File
case 'S': objtyp = MSRFIL; break; //Motorola SREC File
case 'X': objtyp = INTFIL; break; //Intel HEX File
default: xerror("Illegal Command Line Option %s\n", argval);
}
if (debug && objtyp) printf("Object type set to %d\n", objtyp);
return TRUE;
}
@ -766,12 +953,13 @@ int main(int argc, char *argv[]) {
objtyp = BINFIL; //Default Object File Type to Binary
pcargs(argc, argv); //Parse Command Line Arguments
inpfil = opnfil(inpnam, "r", ""); //Open Input File
outfil = opnfil(outnam, "wb", ""); //Open Output File
outfil = opnobj(outnam, ""); //Open Output File
if (lstnam[0]) //If List File Name Specified
lstfil = opnfil(lstnam, "w", ""); // Open List File
asmfil(1); //Assemble Input File (First Pass)
asmfil(2); //Assemble Input File (First Pass)
if (lstfil && symcnt) prtsym(); //Print Symbol Table
clsobj(); //Close Object File
exit(0); //Exit with No Errors
}

33
a02.h
View File

@ -4,15 +4,18 @@
#define MAXLBL 8 //Maximum Symbol Length
#define MAXSYM 1024 //Maximum Number of Labels
//#define NULL &0
#define FALSE 0
#define TRUE -1
/* Address Mode Bit Masks */
#define RGSTR 0x0000 //Register (Sweet 16)
#define ACMLT 0x0001 //Accumulator [$xA]
#define IMMDT 0x0002 //*Immediate [w/Acc]
#define ZPAGE 0x0004 //Zero Page
#define ZPAGX 0x0008 //*Zero Page,X
//#define ZPAGY 0x0010 //*Zero Page,Y [By OpCodes]
#define RGIND 0x0010 //Register or Imderect (Sweet 16)
#define ABSLT 0x0020 //Absolute
#define ABSLX 0x0040 //*Absolute,X [fixops()]
#define ABSLY 0x0080 //Absolute,Y
@ -24,13 +27,15 @@
char zpgabs[][9] = {"Absolute", "ZeroPage"};
/* Address Mode Descriptions */
struct amd {int amode; char desc[12];};
struct amd amdesc[] = {
{ACMLT, "Accumulator"},
{ACMLT, "Accumulator"},
{IMMDT, "Immediate"},
{ZPAGE, "Zero Page"},
{ZPAGX, "Zero Page,X"},
{ABSLT, "Absolute"},
{RGSTR, "Register"},
{ABSLX, "Absolute,X"},
{ABSLY, "Absolute,Y"},
{IMPLD, "Implied"},
@ -45,7 +50,8 @@ struct opc {char name[5], token; int amode;};
struct opc psolst[] = {
{"BYTE", 'B', 0}, {"HEX", 'H'}, {"WORD", 'W', 0}, {"EQU", '=', 0}, {"FILL", 'F', 0},
{"INCL", 'I', 0}, {"SUBR", 'S', 0}, {"DC", 'B', 0}, {"DS", 'F', 0}, {"ALIG", 'A', 0},
{"ORG", '*', 0}, {"PROC", 'P', 0}, {"END", 'E', 0}, {"ENDS", 'M', 0}, {"", 0, 0}
{"ORG", '*', 0}, {"PROC", 'P', 0}, {"END", 'E', 0}, {"ENDS", 'M', 0}, {"EXEC", 'X', 0},
{"DW", 'W', 0}, {"", 0, 0}
};
struct opc opclst[] = {
@ -73,7 +79,7 @@ struct opc opclst[] = {
{"RMB4", 0x47, 0x0004}, {"RMB5", 0x57, 0x0004}, {"RMB6", 0x67, 0x0004}, {"RMB7", 0x77, 0x0004},
{"SMB0", 0x87, 0x0004}, {"SMB1", 0x97, 0x0004}, {"SMB2", 0xA7, 0x0004}, {"SMB3", 0xB7, 0x0004},
{"SMB4", 0xC7, 0x0004}, {"SMB5", 0xD7, 0x0004}, {"SMB6", 0xE7, 0x0004}, {"SMB7", 0xF7, 0x0004},
{"RMB", 0x07, 0x0004}, {"SMB", 0x87, 0x0004},
{"RMB", 0x07, 0x0004}, {"SMB", 0x87, 0x0004},
{"BBR0", 0x0F, 0x1004}, {"BBR1", 0x1F, 0x1004}, {"BBR2", 0x2F, 0x1004}, {"BBR3", 0x3F, 0x1004},
{"BBR4", 0x4F, 0x1004}, {"BBR5", 0x5F, 0x1004}, {"BBR6", 0x6F, 0x1004}, {"BBR7", 0x7F, 0x1004},
@ -113,3 +119,22 @@ struct opf opfix[] = {
{0,0,0}
};
/* Sweet 16 Address Modes
IMPLD - Implied (No Argument)
RGSTR - Register
INDCT - Register Indirect
ABSLT - Register Absolute
RKLTV - Relative (Branch)
RGIND - Register or Indirect
*/
/* Sweet 16 OpCodes */
struct opc swolst[] = {
{"RTN", 0x00, IMPLD}, {"BR", 0x01, RELTV}, {"BNC", 0x02, RELTV}, {"BC", 0x03, RELTV},
{"BP", 0x04, RELTV}, {"BM", 0x05, RELTV}, {"BZ", 0x06, RELTV}, {"BNZ", 0x07, RELTV},
{"BM1", 0x08, RELTV}, {"BNM1", 0x09, RELTV}, {"BK", 0x0A, IMPLD}, {"RS", 0x0B, IMPLD},
{"BS", 0x0C, RELTV}, {"SET", 0x10, ABSLT}, {"LD", 0x20, RGIND}, {"ST", 0x30, RGIND},
{"LD", 0x40, INDCT}, {"ST", 0x50, INDCT}, {"LDD", 0x60, INDCT}, {"STD", 0x70, INDCT},
{"POP", 0x80, INDCT}, {"STP", 0x90, INDCT}, {"ADD", 0xA0, RGSTR}, {"SUB", 0xB0, RGSTR},
{"POPD", 0xC0, INDCT}, {"CPR", 0xD0, RGSTR}, {"INR", 0xE0, RGSTR}, {"DCR", 0xF0, RGSTR}
};

View File

@ -1,11 +1,32 @@
; C02 module intlib.h02 assembly language subroutines
; Requires
; external zero page words DSTPTR and SRCPTR
; and external locations TEMP0, TEMP1, TEMP2, and TEMP3
; Requires external zero page words DSTPTR, SRCPTR,
; external bytes TEMP0, TEMP1, TEMP2, and TEMP3, and
; external words INTACC, INTARG, and INTOVR.
SUBROUTINE INTLIB
;iabs(n) - Get Integer ABSolute Value
;iacc(i) - Set Integer Accumulator to i
;Args: Y,X = Argument
;Sets: INTACC = Y,X
IACC: STX INTACC
STY INTACC+1
RTS
;Set Integer Argument
.SETARG STX INTARG
STY INTARG+1
RTS
;Clear Integer Overflow
;Sets: INTOVR = 0
;Returns A = 0
.CLROVR LDA #0
STA INTOVR
STA INTOVR+1
RTS
;iabs(i) - Get Integer ABSolute Value
;Args: Y,X = Integer to get Absolute Value Of
;Sets: TEMP1, TEMP2
;Affects: C, N, Z
@ -23,188 +44,248 @@ IABS: CPY #$80 ;If Negative (High Bit Set)
;imax(i) - Get MAXimum of Two Integers
;Args: Y,X = Second Integer
;Uses: SRCPTR = First Integer
;Uses: INTACC = First Integer
;Affects: N,Z,C
;Returns: Y,X = Larger of the Two Arguments
IMAX: CPY SRCPTR+1 ;If Y < SRCPTR MSB
BCC .GETSRC ; Return SRCPTR
CPX SRCPTR ;IF X >= SRCPTR LSB
BCS .RETURN ; Return Argument
.GETSRC JMP GETSRC ;Return Integer in SRCPTR
IMAX: CPY INTACC+1 ;If Y < INTACC MSB
BCC .GETACC ; Return INTACC
CPX INTACC ;IF X >= INTACC LSB
BCS .IMSET ; Set INTACC to and Return Argument
.GETACC LDX INTACC ;Return Integer Accumulator
LDY INTACC+1
RTS
;imin(i) - Get MINimum of Two Integers
;Args: Y,X = Second Integer
;Uses: SRCPTR = First Integer
;Uses: INTACC = First Integer
;Sets: IINTACC = Result
;Affects: N,Z,C
;Returns: Y,X = Larger of the Two Arguments
IMIN: CPY SRCPTR+1 ;If Y < SRCPTR+1
IMIN: CPY INTACC+1 ;If Y < INTACC+1
BCC .RETURN ; Return Argument
BNE .GETSRC ;If Y > SRCPTR+1 Return SRCPTR
CPX SRCPTR ;If X >= SRCPTR
BCS .GETSRC ; Return SRCPTR
RTS ;Return Argument
BNE .GETACC ;If Y > INTACC+1
CPX INTACC ;or X >= INTACC
BCS .GETACC ; Return INTACC
.IMSET JMP IACC ;Else Set INTACC to and Return Argument
;iaddc(c,i) - Add Byte c to Integer i
IADDC: JSR SETSRC ;Save Integer and Clear Y
;iaddc(c,i) - Integer ADD Char c to int i
IADDC: JSR IACC ;Store Integer in Accumulator
LDY #0 ;Set Argument MSB to 0
TAX ;Copy Byte to LSB and drop into IADD
;iadd(d) - ADD Integer d to from Integer g
;iand(d) - Integer ADD g + d
;Args: Y,X = Addend
;Requires: setsrc(g) - Augend
;Sets: TEMP1,TEMP2 = Addend
;Affects: Z,C
;Returns: A = Carry
;Requires: IACC(g) - Augend
;Sets: INTACC = Result
;Affects: Z
;Returns: Y,X = Sum
;IAND: TXA ;AND Argument LSB
; AND IACC ;with Accumulator LSB
; TAX
; TYA ;AND Argument MSB
; AND IACC+1 ;with Accumulator MSB
; TAY
; JMP IACC ;Set INTACC to And Return Result
;iadd(d) - Integer ADD g + d
;Args: Y,X = Addend
;Requires: IACC(g) - Augend
;Sets: INTACC = Sum
;Affects: Z
;Returns: A,C = Carry
; Y,X = Sum
; N = Sign of Result
IADD: CLC ;Clear Carry for Addition
TXA ;Add Addend LSB
ADC SRCPTR ;to Augend LSB
TAX ;and Copy to X
TYA ;Add Addend MSB
ADC SRCPTR+1 ;to Augebd MSB
TAY ;and Copy to Y
LDA #0 ;Set Overflow to 0
ROL ; Rotate Carry (Same as Adding it)
RTS ; and Return
IADD: CLC ;Clear Carry for Addition
TXA ;Add Addend LSB
ADC INTACC ;to Augend LSB
TAX ;and Copy to X
TYA ;Add Addend MSB
ADC INTACC+1 ;to Augebd MSB
TAY ;and Copy to Y
PHP ;Save Result Flags
LDA #0 ;Clear CHR Result to 0
STA INTOVR+1 ; and Clear Overflow MSB
ROL ;Rotate Carry Flag into CHR Result
STA INTOVR ; and store in INTOVR
PLP ;Restore Result Flags
JMP IACC ;Set INTACC to And Return Result
;isub(s) - SUBtract Integer s from Integer m
;ineg(i) - Integer NEGate int i
;Args: Y,X = Integer to Negate
;Sets: INTACC = Result
; INTARG = Argument
;Returns: Y,X = Negated Integer
; N = Sign of Result
INEG: LDA #0 ;Set Minuend to Zero
STA INTACC
STA INTACC+1
;isub(s) - Integer SUBtract m - s
;Args: Y,X = Subtrahend
;Requires: setsrc(m) - Minuend
;Sets: TEMP1,TEMP2 = Subtrahend
;Affects: Z,C
;Returns: A = Carry
;Requires: IACC(m) - Minuend
;Sets: INTACC = Difference
; INTARG = Subtrahend
;Affects: Z
;Returns: A,C = Carry
; Y,X = Difference
; N = Sign of Result
ISUB: JSR SAVRXY ;Store Subtrahend in TEMP1,TEMP2
SEC ;Set Carry for Subtraction
LDA SRCPTR ;Load Minuend LSB
SBC TEMP1 ;Subtract Subtrahend LSB
TAX ;Copy Difference LSB to X
LDA SRCPTR+1 ;Load Minuend MSB
SBC TEMP2 ;Subtract Subtrahend MSB
TAY ;Copy Difference MSB to Y
LDA #0 ;Set Overflow Byte to 0
SBC #0 ; Subtract Carry
RTS ; and Return
ISUB: JSR .SETARG ;Store Subtrahend in INTARG
SEC ;Set Carry for Subtraction
LDA INTACC ;Load Minuend LSB
SBC INTARG ;Subtract Subtrahend LSB
TAX ;Copy Difference LSB to X
LDA INTACC+1 ;Load Minuend MSB
SBC INTARG+1 ;Subtract Subtrahend MSB
TAY ;Copy Difference MSB to Y
PHP ;Save Result Flags
LDA #0 ;Set Overflow Byte to 0
SBC #0 ;and Subtract Carry
PLP ;Restore Result Flags
JMP IACC ;Set INTACC to And Return Result
;imultc(c,m) - Multiply Int m by Char c
;Args: A - Multiplicand
; Y,X - Multiplier
;Sets: INTACC - Product MSB, LSB
IMULTC: STA INTACC ;Set Integer Accumulator to int(A)
LDA #0
STA INTACC+1 ;and execute IMULT
;imult(m) - MULTiply Two Integers
;Args: Y,X - Multiplier
;Requires: DSTPTR = Multiplicand
;Sets: TEMP0-TEMP3 = 32 Bit Product
;Destroys: SRCPTR
;Affects: A,C,Z,N
;imult(m) = MULTiply Integer n * Integer m
;Args: Y,X = Multiplier
;Uses: INTACC = Multiplicand
;Sets: INTACC = Product MSB, LSB
;Sets: INTOVR = Product MSB, LSB
;Destroys: TEMP0,TEMP1,TEMP2,TEMP3
;Affects: C,Z,N
;Returns: A,Y,X = 24 Bit Product
IMULT: JSR SETSRC ;Save Multiplier
STY TEMP0+2 ;Clear Upper Bits of Product
STY TEMP0+3
IMULT: JSR .SETARG ;Save Multiplier
LDY #0
STY INTOVR ;Clear Upper Bits of Product
STY INTOVR+1
LDX #16 ;Rotate Through 16 Bits
.MSHFTR LSR SRCPTR+1 ;Divide Multiplier by 2
ROR SRCPTR
.MSHFTR LSR INTARG+1 ;Divide Multiplier by 2
ROR INTARG
BCC .MROTR ;If Shifted out Bit is 1
LDA TEMP0+2 ; Add Multiplicand
LDA INTACC ; Add Multiplicand
CLC ; to Upper Half of Product
ADC DSTPTR
STA TEMP0+2
LDA TEMP0+3
ADC DSTPTR+1
STA TEMP0+3
.MROTR ROR TEMP0+3
ROR TEMP0+2
ROR TEMP0+1
ADC INTOVR
STA INTOVR
LDA INTOVR+1
ADC INTACC+1
STA INTOVR+1
.MROTR ROR INTOVR+1
ROR INTOVR
ROR TEMP1
ROR TEMP0
DEX ;Decrement Counter
BNE .MSHFTR ;and Process Next Bit
LDX TEMP0
LDY TEMP1 ;Return Low 24 Bits of
LDA TEMP2 ;Product in A, Y, and X
RTS
LDA INTOVR ;Get Bits 16-24 of Result
LDY TEMP1 ;Get Bits 8-15 of Result
LDX TEMP0 ;Get Bits 0-7 of Result
JMP IACC ;Store Y,X in INTACC and Return in Y,X
;idiv(d) - Integer DIVide
;imod(d) - Integer MODulus d % s
;Args: Y,X - Divisor
;Requires: DSTPTR = Dividend
;Sets: SRCPTR = Divisor
; DSTPTR = Quotient
; TEMP1,TEMP2 = Remainder
;Requires: IACC(d) = Dividend
;Sets: INTARG = Divisor
; INTACC, INTOVR = Modulus
;Affects: A,C,Z,N
;Returns: Y,X = 16 Bit Modulus
IMOD: JSR IDIV ;Do Division
LDX INTOVR ;get Remainder
LDY INTOVR+1 l
JMP IACC ;Store in INTACC and Return in Y,X
;idiv(s) - Integer DIVide d / s
;Args: Y,X - Divisor
;Requires: IACC(d) = Dividend
;Sets: INTARG = Divisor
; INTACC = Quotient
; INTOVR = Remainder
;Affects: A,C,Z,N
;Returns: Y,X = 16 Bit Quotient
IDIV: JSR .IDIV ;Do Division and
JMP GETDST ;Return Quotient
;imod(d) - Integer MODulus
;Args: Y,X - Divisor
;Requires: DSTPTR = Dividend
;Sets: SRCPTR = Divisor
; DSTPTR = Quotient
; TEMP1,TEMP2 = Remainder
;Affects: A,C,Z,N
;Returns: Y,X = 16 Bit Remainder
IMOD: JSR .IDIV ;Do Division and
JMP RESRXY ;Return Remainder
.IDIV JSR SETSRC ;Save Divisor
STY TEMP1
STY TEMP1+1
IDIV: JSR .SETARG ;Save Divisor
LDY #0
STY INTOVR
STY INTOVR+1
LDX #16 ;repeat for each bit: ...
.IDLOOP ASL DSTPTR ;dividend lb & hb*2, msb -> Carry
ROL DSTPTR+1
ROL TEMP1 ;remainder lb & hb * 2 + msb from carry
ROL TEMP1+1
LDA TEMP1
.IDLOOP ASL INTACC ;dividend lb & hb*2, msb -> Carry
ROL INTACC+1
ROL INTOVR ;remainder lb & hb * 2 + msb from carry
ROL INTOVR+1
LDA INTOVR
SEC
SBC SRCPTR ;subtract divisor to see if it fits in
SBC INTARG ;subtract divisor to see if it fits in
TAY ;lb result -> Y, for we may need it later
LDA TEMP1+1
SBC SRCPTR+1
LDA INTOVR+1
SBC INTARG+1
BCC .IDSKIP ;if carry=0 then divisor didn't fit in yet
STA TEMP1+1 ;else save substraction result as new remainder,
STY TEMP1
INC DSTPTR ;and INCrement result cause divisor fit in 1 times
STA INTOVR+1 ;else save substraction result as new remainder,
STY INTOVR
INC INTACC ;and INCrement result cause divisor fit in 1 times
.IDSKIP DEX
BNE .IDLOOP
RTS
JMP .GETACC ;Return Integer Accumulator
;ishftl(n,i) - Shift Integer i to the Left n Bits
;Sets: TEMP1, TEMP2 = LSB, MSB of Result
;Affects: A,Y,N,Z,C
;Returns: A = Bits Shifted out of Integer
;Args: A = Number of Bits to Shift
; Y,X = Integer Value to Shift
;Sets: INTACC = Bits 0 to 15 of Result
; INTOVR = Bits 16 to 31 of Result
;Sets: INTACC = Shifted Intger
;Affects: N,Z,C
;Returns: A = LSB of Underflow
; Y,X = Shifted Integer
ISHFTL: JSR SAVRXY ;Save X,Y in TEMP1,TEMP2
TAY ;Set Counter to Number of Bits
BEQ .RESRXY ;If Zero, Return
LDA #0 ;Clear Overflow
.LSLOOP ASL TEMP1 ;Shift LSB to Left
ROL TEMP2 ;Rotate MSB to Left
ROL ;Rotate Carry into A
DEY ;Decrement Counter
ISHFTL: JSR IACC ;Save Argument in INTACC
LDX #0 ;Clear Overflow
STX INTOVR
STX INTOVR
TAX ;Set Counter to Number of Bits
BEQ .LSDONE ;If Zero, Return 0
.LSLOOP ASL INTACC ;Shift Bits 0-7 to Left
ROL INTACC+1 ;Rotate Bits 8-15 to Left
ROL INTOVR ;Rotate Bits 16-23 to Left
ROL INTOVR+1 ;Rotate Bits 24-31 to Left
DEX ;Decrement Counter
BNE .LSLOOP ; and Loop if Not 0
BEQ .RESRXY ;Return Shifted Integer
LDA INTOVR ;Return Bits 16-23 in A
.LSDONE JMP .GETACC ;and Bits 0-15 in Y,X
;ishftr(n,i) - Shift Integer i to the Right n Bits
;Sets: TEMP1, TEMP2 = LSB, MSB of Result
;Affects: A,Y,N,Z,C
;Returns: A = Bits Shifted out of Integer
; Y,X = Shifted Integer
ISHFTR: JSR SAVRXY ;Save X,Y in TEMP1,TEMP2
TAY ;Set Counter to Number of Bits
BEQ .RESRXY ;If Zero, Return
LDA #0 ;Clear Overflow
.RSLOOP LSR TEMP2 ;Shift MSB to Right
ROR TEMP1 ;Rotate LSB to Right
ROR ;Rotate Carry into A
DEY ;Decrement Counter
;Args: A = Number of Bits to Shift
; Y,X = Integer Value to Shift
;Sets: INTACC = Bits 0 to 15 of Result
; INTOVR = Bits -1 to -16 of Result
;Sets: INTACC = Shifted Intger
;Affects: N,Z,C
;Returns: A = MSB of Underflow
; Y,X = Shifted Result
ISHFTR: JSR IACC ;Save Argument in INTACC
LDX #0 ;Clear Overflow
STX INTOVR
STX INTOVR
TAX ;Set Counter to Number of Bits
BEQ .RSDONE ;If Zero, Return Argument
.RSLOOP LSR INTACC+1 ;Shift MSB to Right
ROR INTACC ;Rotate LSB to Right
ROR INTOVR+1 ;Rotate Underflow MSB
ROR INTOVR ;Rotate Underflow LSB
DEX ;Decrement Counter
BNE .RSLOOP ; and Loop if Not 0
BEQ .RESRXY ;Load Shifted Integer and Return
LDA INTOVR+1 ;Return Underflow MSB in A
.RSDONE JMP .GETACC ;and Result in Y,X
;atoi(&s) - ASCII string TO Integer
;Args: Y,X = Address of String to Convert
;Sets: TEMP1, TEMP2 = Integer Value
;Affects: TEMP0
;Sets: INTACC = Integer Value
;Affects: TEMP0,TEMP1,TEMP2
;Returns: A = Number of Digits
; Y,X = Integer Value
ATOI: JSR SETSRC ;Initialize Source String
STY TEMP1 ;Initialize Result
STY TEMP2
.AILOOP LDA (SRCPTR),Y ;Get Next Character
.AILOOP LDA (SRCPTR),Y ;Get Next Character
CMP #$30 ;If Less Than '0'
BCC .AIDONE ; Exit
CMP #$3A ;If Greater Than '9'
@ -235,14 +316,18 @@ ATOI: JSR SETSRC ;Initialize Source String
INY ;Increment Index
BPL .AILOOP ; and Loop
.AIDONE TYA ;Return Number of Digits
.RESRXY JMP RESRXY ;and Integer Value
.RESRXY JSR RESRXY ;and Integer Value
JMP IACC
;itoa(n) - Integer TO ASCII string
;Args: Y,X = Integer Value to Convert
;itoa(&d) - Integer TO ASCII string
;Args: Y,X = Address of Destination String
;Uses: INTACC = Integer to Convert
;Uses: DSTPTR = Destination String
;Affects: X
;Returns: A,Y = Length of String
ITOA: JSR CVIBCD ;Convert Integer to Packed BCD
ITOA: JSR SETDST ;Store String Pointer Agrumenr
JSR .GETACC ;Load INTACC
JSR CVIBCD ;Convert Integer to Packed BCD
LDY #0 ;Initialize Index into String
STY TEMP3
.ITOAA LDY #4 ;Set Initial Digit Number
@ -250,24 +335,25 @@ ITOA: JSR CVIBCD ;Convert Integer to Packed BCD
BNE .IASKIP ;If Zero
DEY ; Decrement Digit Number
BNE .IAZERO ; If Not Zero Loop
BEQ .IASKIP ; Else .IDSKIP Unpack
BEQ .IASKIP ; Else Branch into .IALOOP
.IALOOP JSR UPBCDI ;Unpack Digit #Y
.IASKIP TAX ;Save Digit in X
TYA ;Push Digit Number into Stack
TYA ;Push Unpack Index into Stack
PHA
TXA ;and Restore Digit
LDY TEMP3 ;Get Index into String
ORA #$30 ;Convert Digit to ASCII
LDY TEMP3 ;Get Index into String
STA (DSTPTR),Y ;and Store in String
INC TEMP3 ;Increment Index into String
PLA ;Pull Digit Number off Stack
TAY
DEY ;Decrement Digit Number
BPL .IALOOP ;Loop if >= Zero
BPL .IALOOP ;Loop if >= Zero
LDA #0 ;Terminate String
STA (DSTPTR),Y
TYA ;Return String Length
RTS
JMP .GETACC ;and INTACC
;upbcdi() - UnPack digits from BCD Integer
; Assumes that TEMP0, TEMP1, and TEMP2
@ -298,21 +384,17 @@ UPBCDI: PHP
; TEMP1 = Thousands and Hundreds Digit
; TEMP2 = Ten-Thousands Digit
;Affects: A
CVIBCD: LDA #0 ;Clear BCD Bytes
CVIBCD: JSR IACC ;Store Argument
LDA #0 ;Clear BCD Bytes
STA TEMP0
STA TEMP1
STA TEMP2
PHP ;Save Status Register
SEI ;Disable Interrupts
SED ;Set Decimal Mode
TYA ;Push MSB onto Stack
PHA
TXA ;Push LSB onto Stack
PHA
TSX ;Copy Stack Pointer to X
LDY #16 ;Process 16 bits of Binary
.CVLOOP ASL $101,X ;Shift High Bit Into Carry
ROL $102,X
.CVLOOP ASL INTACC ;Shift High Bit Into Carry
ROL INTACC+1
LDA TEMP0 ;Add 6 Digit BCD Number Itself
ADC TEMP0 ; Effectively Multiplying It by 2
STA TEMP0 ; and Adding in the Shifted Out Bit
@ -324,9 +406,27 @@ CVIBCD: LDA #0 ;Clear BCD Bytes
STA TEMP2
DEY ;Decrement Counter and
BNE .CVLOOP ; Process Next Bit
PLA ;Restore X and Y Registers
PLA
PLP ;Restore Status Register
RTS
;icmp(j) - Compare Int i to Int j
;Requires: IACC(i) - int to compare against
;Args: X,Y = int to compare
; N based on return value of A
;Returns A=$01 and C=1 if INTACC > Arg
; A=$00 and Z=1, C=1 if INTACC = Arg
; A=$FF and C=0 if INTACC < Arg
ICMP: CPY INTACC+1 ;Compare MSBs
BCC .GT ;INTACC < Y,X
BNE .LT ;INTACC > Y,X
CPX INTACC ;Compare LSBs
BCC .GT ;INTACC < Y,X
BNE .LT ;INTACC > Y,X
LDA #0
RTS ;Return INTACC = YX
.LT LDA #$FF
RTS ;Return INTACC < YX
.GT LDA #1
RTS ;Return INTACC > YX
ENDSUBROUTINE

View File

@ -2,77 +2,115 @@
* intlib - Standard Library Routines for Integer Values *
*********************************************************/
/* Integer Absolute Value *
* Args: int w - Integer to test *
* Returns: int v -Absolute value of w */
/* Set Integer Accumlator *
* Args: int w - Integer value *
* Sets: iacc = Argument *
* Returns: int w - Argument */
char iacc();
/* Integer Absolute Value *
* Args: int w - Integer value *
* Sets: iacc = Result *
* Returns: int v - Absolute value of w */
char iabs();
/* Integer Add *
* Setup: setsrc(g) - Augend *
* Args: int d - Addend *
* Returns: char c - Carry *
* int r - Sum */
/* Integer Add: g + d *
* Setup: iset(g) - Augend *
* Args: int d - Addend *
* Sets: iacc, iover = Result *
* Returns: char c - Carry *
* int r - Sum */
char iadd();
/* Integer Add Char: c + d *
* Args: char c - Augend *
* int d - Addend *
* Sets: iacc, iover = result *
* Returns: char c - Carry *
* int r - Sum */
char iaddc();
/* ASCII to Integer *
* Convert ASCII string to Unsigned Integer *
* Args: &s - String to Convert *
* Sets: iacc = Result *
* Returns: char n - Number of digits parsed *
* int v - Numeric value of string */
char atoi();
/* Integer to ASCII *
* Convert Unsigned Integer to String *
* Setup: setdst(s) - Destination String *
* Args: int w - Unsigned Int to Convert *
* Returns: char n - Length of string */
/* Integer to ASCII *
* Convert Unsigned Integer to String *
* Setup: iset(i) - Unsigned Int to Convert *
* Args: &s - Destination String *
* Sets: iacc = Argument *
* Returns: char n - Length of string */
void itoa();
/* Integer Divide *
* Divide Unsigned Integers *
* Aetup: setdst(n) - Numerator *
* Args: int d - Denominator *
* Returns: int q - Quotient */
/* Integer unsigned Divide *
* Aetup: iset (n) - Numerator *
* Args: int d - Denominator *
* Sets: iacc = Quotient *
* Returns: int q - Quotient */
char idiv();
/* Integer Maximum *
/* Integer unsigned Maximum *
* Return Largest of Two Integers *
* Requires: setsrc(i) - First Integer *
* Setup: iset(i) - First Integer *
* Args: int j - Second Integer *
* Sets: iacc = Result *
* Returns: int m - Greater of the Two */
char imax();
/* Integer Minimum *
* Return smallest of Two Integers *
* Requires: setsrc(i) - First Integer *
* Args: int j - Second Integer *
* Returns: int m - Lesser of the Two */
/* Integer unsigned Minimum *
* Return smallest of Two Integers *
* Setup: setsrc(i) - First Integer *
* Args: int j - Second Integer *
* Sets: iacc = Result *
* Returns: int m - Lesser of the Two */
char imin();
/* Integer Multiply *
* Multiply Unsigned Integers *
* Requires: setdst(m) - Muliplicand *
* Args: int r - Multiplier *
* Returns: long p - Product */
/* Integer unsigned Modulo *
* Aetup: iset(n) - Numerator *
* Args: int d - Denominator *
* Sets: iacc = Result *
* Returns: int q - Modulus */
char idiv();
/* Integer unsigned Multiply: m * r *
* Setup: iset(m) - Muliplicand *
* Args: int r - Multiplier *
* Sets: iacc, iover = 32 bit Product *
* Returns: long p - 24 bit Product */
char imult();
/* Integer Left Shift *
* Args: char n - Number of Bits *
* int w - Value to Shift *
* Returns: char v - Overflow Bits *
int r - Shifted Integer */
/* Integer Multiply Char: c * r *
* Args: int c - Multplicand
* int r - Multiplier *
* Sets: iacc, iover = 32 bit Product *
* Returns: long p - 24 bit Product */
char imult();
/* Integer Shift Left *
* Args: char n - Number of Bits *
* int w - Value to Shift *
* Sets: iacc = Integer result *
* iover = Integer Overflow *
* Returns: long p - 24 bit Result */
char ishftl();
/* Integer Shift Right *
/* Integer Shift Right *
* Args: char n - Number of Bits *
* int w - Value to Shift *
* Returns: char v - Overflow Bits *
* Sets: iacc = Integer result *
* iover = Integer Underflow *
* Returns: char u - Underflow Bits *
int r - Shifted Integer */
char ishftr();
/* Integer Subtract *
* Requires: setsrc(m) - Minuend *
* Args: int s - Subtrahend *
* Returns: char c - Carry *
* int d - Difference */
/* Integer Subtract: m - s *
* Setup: iaet(m) - Minuend *
* Args: int s - Subtrahend *
* Sets: iacc, iover = result *
* Returns: char c - Carry *
* int d - Difference */
char isub();

View File

@ -5,48 +5,70 @@ DELKEY EQU $08 ;Delete/Backspace Key (Backspace)
ESCKEY EQU $1B ;Escape/Stop Key (Escape)
RTNKEY EQU $0D ;Return/Enter Key (Carriage Return)
;Zero Page Locations
SRCPTR EQU $30 ;Source String Pointer
DSTPTR EQU $32 ;Destination String Pointer
BLKPTR EQU $34 ;Block Segment Pointer
STKPTR EQU $36 ;Stack Pointer
USRPTR EQU $38 ;User Pointer
;Zero Page Variables
; $00-$06 ;Reserved
XMADDR EQU $3A ;Extended Memory Address
XMBANK EQU $3C ;Extended Memory Bank
; $3D ;Unused
XMBANK EQU $07 ;Extended Memory Bank
XMADDR EQU $08 ;Extended Memory Address
RDSEED EQU $3E ;Pseudo-RANDOM Seed
RANDOM EQU $3F ;Pseudo-RANDOM Number Storage
SRCPTR EQU $10 ;Source Pointer
DSTPTR EQU $12 ;Destination Pointer
TEMP0 EQU $40 ;Temporary Storage
TEMP1 EQU $41
TEMP2 EQU $42
TEMP3 EQU $43
TMPPTR EQU $44 ;Temporary Pointer
TEMP0 EQU $14 ;Temporary Storage
TEMP1 EQU $15
TEMP2 EQU $16
TEMP3 EQU $17
TMPPTR EQU $18 ;Temporary Pointer
BLKBGN EQU $46
BLKEND EQU $48
BLKLEN EQU $4A ;Block Segment Length
SYSBFP EQU $4B ;Position in System Buffer
STKBGN EQU $4C ;Stack Start Address
STKEND EQU $4E ;Stack End Address
; $50-$FF ;Free Zero Page for Applications
LSTPTR EQU $1A ;List Pointer
USRPTR EQU $1C ;User Pointer
; $1E ;Reserved
BLKLEN EQU $1F ;Block Segment Length
BLKPTR EQU $20 ;Block Segment Pointer
BLKBGN EQU $22 ;Block Start Address
BLKEND EQU $24 ;Block End Address
STKPTR EQU $26 ;Stack Pointer
STKBGN EQU $28 ;Stack Start Addres
STKEND EQU $2A ;Stack End Address
RDSEED EQU $2C ;Pseudo-RANDOM Seed
RANDOM EQU $2D ;Pseudo-RANDOM Number Storage
SYSBFP EQU $2E ;Position in System Buffer
.STKSAV EQU $2F ;Stack Pointer Storage
INTACC EQU $30 ;Integer Accumulator
INTOVR EQU $32 ;Integer Overflow
INTARG EQU $34 ;Integer Argument
; $34-$3F ;Reserved
; $40-$FF ;Free Zero Page for Applications
SYSBFL EQU 128 ;System Buffer Size (Max String Size)
SYSBFR EQU $0200 ;System Buffer
; $0281-$03FF ;Unused
;Memory Mapped I/O
_KBHIT EQU $FFF0 ;Is a Key Pressed
_GETCH EQU $FFF1 ;Read Keyboard (Blocking)
;Emulated BIOS System Calls
.GETCH EQU $FFE0 ;-K Read Keyboard
.PUTCH EQU $FFE3 ;-C Write to Screen
FSCMD EQU $FFE6 ;-F filecmd() - File I/O Command Processor
SYSCMD EQU $FFE9 ;-S syscmd() - System Command Processor
XMCMD EQU $FFEC ;-E Extended Memory
.STDIO EQU $FFEF ;-M Memory Mapped stdio
EXIT EQU $FFF0 ;-X Exit Emulator
; $0000 ;-N NMI Vector
ARGV EQU $0300 ;Command Line Arguments Bu
ORG $0400 ;START at RAM midpoint
START: JMP MAIN ;Execute Program
;Read Character from Console
GETKEY EQU $FFE0 ;Emulator _GETCH Routine
GETKEY EQU .GETCH ;Emulator _GETCH Routine
;Poll Character from Keyboard
POLKEY: BRK ;Exit Emulator
@ -58,7 +80,7 @@ GETCHR: JSR GETKEY ;Get Key from Console
RTS
;Read Character from stdin
RDCHAR: LDA $FFEA ;Read Character from STDIN
RDCHAR: LDA .STDIO ;Read Character from STDIN
CMP #$FF ;If EOF
BNE RDCHAX
LDA #0 ; Set to ASCII NUL
@ -80,16 +102,12 @@ NEWLIN: LDA #$0D ;Load Carriage Return into Accumulator
JMP PUTCHR ; and Print it
;Print Character to Console
PUTCHR EQU $FFE3 ;Emulator CHROUT Routine
PUTCHR EQU .PUTCH ;Emulator CHROUT Routine
;Write Character to stdout
PRCHAR: STA $FFEA ;Read Character from STDIN
PRCHAR: STA .STDIO ;Read Character from STDIN
RTS
EXIT EQU $FFEC ;Emulator SHUTDN Routine
FSCMD EQU $FFE6 ;run6502 File System Command Routine
INCLUDE "prbyte.a02" ;PRBYTE and PRHEX routines
INCLUDE "putstr.a02" ;PUTSTR routine

View File

@ -1,25 +1,26 @@
/* run6502 Header File */
/* Platform Specific Settings */
#pragma zeropage $50 $FF //Zero Page Free Space
#pragma zeropage $40 $FF //Zero Page Free Space
/* Platform Specific Constants */
#define DELKEY $08 //Delete/Backspace Key
#define DELKEY $7F //Delete/Backspace Key
#define ESCKEY $1B //Escape/Stop Key
#define RTNKEY $0D //Return/Enter Key
#define SYSBFL 128 //System Buffer Length
/* Standard Library Variables */
zeropage int srcptr, dstptr; //Source and Destination Pointer
zeropage int blkptr, stkptr; //Block and Stack Pointers
zeropage int tmpptr, usrptr; //Temporary and User Pointer
int stkbgn, stkend; //Stack Begin and End Address
int blkbgn, blkend; //Block Begin and End Address
char blklen, xmbank; //Block Segment Length, Ext Memory Bank
int xmaddr; //Extended Memory Address
char random, rdseed; //Pseudo-Random Number and Seed
char temp0, temp1, temp2, temp3; //Temporary Storage
char sysbfr[], sysbfp; //System String Buffer and Position
zeropage int srcptr, dstptr; //Source and Destination Pointer
zeropage int blkptr, stkptr; //Block and Stack Pointers
zeropage int tmpptr, lstptr, usrptr; //Temporary and User Pointer
int stkbgn, stkend; //Stack Begin and End Address
int blkbgn, blkend; //Block Begin and End Address
char blklen, xmbank; //Block Segment Length, Ext Memory Bank
int xmaddr; //Extended Memory Address
int intacc, intarg, intovr; //Integer Accumulator, Argument, Overflow
char random, rdseed; //Pseudo-Random Number and Seed
char temp0, temp1, temp2, temp3; //Temporary Storage
char sysbfr[], sysbfp; //System String Buffer and Position
/* System Subroutines */
void delchr(); //Delete previous character
@ -29,6 +30,7 @@ void newlin(); //Advance cursor to beginning of next line
char polkey(); //Poll Console for character
void prbyte(); //Print Accumulator as Hexadecimal number
void prhex(); //Print Low Nybble of Accumulator as Hex Digit
void prword(); //Print Low Nybble of Accumulator as Hex Digit
char putchr(); //Print ASCII character to Console
char putstr(); //Print ASCII string to Console

View File

@ -16,44 +16,70 @@ char s[128]; //Test String
char cval,cnum,ctot; //Character Function Variables
int ivar,ival; //Integer Variables
int icmp,itot,ires; //Function Variables
int ichk,itot,ires; //Function Variables
int less, more; //Test Values for imin() and imax()
int yx, dd; //Function Arguments and Variables
void cpival(icmp) {
if (>ival <> >icmp or <ival <> <icmp) {
putwrd(ival); puts("<>"); putwrd(icmp);
void cpcval(cnum) {
if (cval <> cnum) {
puthex(cval); puts("<>"); puthex(cnum);
failln();
goto exit;
}
}
/* Test imin() and imax() */
void minmax() {
void cpival(ichk) {
if (>ival <> >ichk or <ival <> <ichk) {
prword(ival); puts("<>"); prword(ichk);
failln();
goto exit;
}
}
/* Test imin() and imax() and icmp() */
void minmax(ctot) {
newlin();
puts("LESS=$"); putwrd(less); puts(",MORE=$"); putwrd(more); newlin();
puts(" IMIN()=$"); setsrc(less);
ival = imin(more); putwrd(ival); newlin();
puts("IMIN(IACC($"); prword(less); puts("),$"); prword(more); puts(")=$");
ival = imin(iacc(less),more); prword(ival); newlin();
cpival(less);
puts(" IMAX()=$"); setsrc(less);
ival = imax(more); putwrd(ival); newlin();
puts("IMIN(IACC($"); prword(more); puts("),$"); prword(less); puts(")=$");
ival = imin(iacc(more),less); prword(ival); newlin();
cpival(less);
puts("IMAX(IACC($"); prword(less); puts("),$"); prword(more); puts(")=$");
iacc(less); ival = imax(more); prword(ival); newlin();
cpival(more);
puts("IMIN(IACC($"); prword(more); puts("),$"); prword(less); puts(")=$");
iacc(more); ival = imax(less); prword(ival); newlin();
cpival(more);
puts("ICMP(IACC($"); prword(less); puts("),$"); prword(more); puts(")=$");
cval = icmp(iacc(less),more); puthex(cval); newlin();
cpcval(-ctot);
puts("ICMP(IACC($"); prword(more); puts("),$"); prword(less); puts(")=$");
cval = icmp(iacc(more),less); puthex(cval); newlin();
cpcval(ctot);
}
/* Test cvibcd() and upbcdi() */
void intbcd(ival) {
newlin(); puts("CVIBCD($"); putwrd(ival); puts(")=$");
newlin(); puts("CVIBCD($"); prword(ival); puts(")=$");
cvibcd(ival); puthex(temp2); puthex(temp1); puthex(temp0);
newlin(); puts("UPBCDI()=");
for (cnum=4; cnum:+; cnum--) {if(cnum<4) {putc(',');} putnyb(upbcdi(0,cnum));}
}
/* Test itoa() and atoi() */
void itaati(ivar) {
newlin();
puts("ITOA($"); putwrd(ivar); puts(")=\"");
setdst(s); size = itoa(ivar); puts(s); putln("\"");
//intbcd(ivar); newlin();
puts("ITOA(IACC($"); prword(ivar); puts(",S); ");
iacc(ivar); size = itoa(s); puts(" S=\""); puts(s); putln("\"");
puts("ATOI(\""); puts(s); puts("\")=$");
ival = atoi(s); putwrd(ival); newlin();
ival = atoi(s); prword(ival); newlin();
cpival(ivar);
}
@ -62,11 +88,11 @@ void itaati(ivar) {
void addsub(ivar) {
newlin();
putint(ival); putc('+'); putint(ivar); putc('=');
setsrc(ival); ctot, itot = iadd(ivar);
putint(itot); puts(" carry=$"); puthex(ctot); newlin();
iacc(ival); ctot, itot = iadd(ivar);
putint(itot); puts(", carry="); prhex(ctot); newlin();
putint(itot); putc('-'); putint(ivar); putc('=');
setsrc(itot); ires = isub(ivar);
putint(itot); puts(" carry=$"); puthex(ctot); newlin();
iacc(itot); ires = isub(ivar);
putint(itot); puts(", carry="); prhex(ctot); newlin();
cpival(ires);
}
@ -74,15 +100,15 @@ void addsub(ivar) {
void mltdiv(ivar) {
newlin();
putint(ival); putc('*'); putint(ivar); putc('=');
setdst(ival); cval,itot = imult(ivar); putint(itot);
iacc(ival); cval,itot = imult(ivar); putint(itot);
if (cval) puts(" OVERFLOW!"); newlin();
putint(itot); putc('/'); putint(ivar); putc('=');
setdst(itot); ires = idiv(ivar); putint(ires); newlin();
iacc(itot); ires = idiv(ivar); putint(ires); newlin();
cpival(ires);
ival>>; setsrc(ival); cval,itot = iadd(itot);
ival>>; iacc(ival); cval,itot = iadd(itot);
if (cval) return; //Number to Large to Modulo
putint(itot); putc('%'); putint(ivar); putc('=');
setdst(itot); ires = imod(ivar); putint(ires); newlin();
iacc(itot); ires = imod(ivar); putint(ires); newlin();
cpival(ires);
}
@ -110,50 +136,55 @@ void shftlr(cval, ivar) {
cpival(itot);
}
main:
less = $009A; more = $00DE; minmax();
less = $789A; more = $78DE; minmax();
less = $7800; more = $BC00; minmax();
less = $789A; more = $BCDE; minmax();
less = $F18F; more = $F18F; minmax();
less = $009A; more = $00DE; minmax(1);
less = $789A; more = $78DE; minmax(1);
anykey();
less = $7800; more = $BC00; minmax(1);
less = $789A; more = $BCDE; minmax(1);
less = $F18F; more = $F18F; minmax(0);
anykey();
itaati(&0);
itaati(&234);
itaati(&256);
itaati(&456);
itaati(&23456);
itaati(&$FFFF);
anykey();
doasc:
//itaati(&0);
itaati(&234);
itaati(&256);
itaati(&456);
itaati(&23456);
itaati(&$FFFF);
anykey();
ival = &23; addsub(&34);
ival = &1234; addsub(&5678);
ival = &23456; addsub(&34567);
ival = &$7700; addsub(&$6600);
ival = &$7FFF; addsub(&$8000);
ival = &$FDEC; addsub(&$CDEF);
anykey();
doadd:
ival = &23; addsub(&34);
ival = &1234; addsub(&5678);
ival = &23456; addsub(&34567);
ival = &$7700; addsub(&$6600);
ival = &$7FFF; addsub(&$8000);
ival = &$FDEC; addsub(&$CDEF);
anykey();
domlt:
ival = &23; mltdiv(&34);
ival = &123; mltdiv(&234);
ival = &255; mltdiv(&257);
anykey();
ival = &23; mltdiv(&34);
ival = &123; mltdiv(&234);
ival = &255; mltdiv(&257);
anykey();
shftlr(0,&$AA55);
shftlr(1,&$A55A);
shftlr(2,&$F00F);
shftlr(3,&$0FF0);
shftlr(4,&$AA55);
shftlr(7,&$A55A);
anykey();
shftlr(8,&$AA55);
shftlr(9,&$A55A);
shftlr(11,&$0FF0);
shftlr(12,&$AA55);
shftlr(15,&$A55A);
shftlr(16,&$F00F);
doshft:
shftlr(0,&$AA55);
shftlr(1,&$A55A);
shftlr(2,&$F00F);
shftlr(3,&$0FF0);
shftlr(4,&$AA55);
shftlr(7,&$A55A);
anykey();
shftlr(8,&$AA55);
shftlr(9,&$A55A);
shftlr(11,&$0FF0);
shftlr(12,&$AA55);
shftlr(15,&$A55A);
shftlr(16,&$F00F);
anykey();
goto exit;