mirror of
https://github.com/RevCurtisP/C02.git
synced 2024-11-23 23:33:03 +00:00
Modified intlib to use system vars intacc, intarg, and intovr
This commit is contained in:
parent
8495b43011
commit
a220bd0592
224
a02.c
224
a02.c
@ -1,7 +1,6 @@
|
|||||||
/* Simple 6502 Assembler *
|
/* 6502 Assembler for C02 Compiler *
|
||||||
* for C02 Compiler *
|
* Uses DASM Syntax but supports *
|
||||||
* Uses DASM Syntax but *
|
* 65C02 and Sweet 16 Opcodes */
|
||||||
* supports 65C02 Op Codes */
|
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -15,13 +14,23 @@ int debug; //Ouput Debug Info
|
|||||||
#define INCLEN 255
|
#define INCLEN 255
|
||||||
char incpath[INCLEN];
|
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
|
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 orgadr; //Origin Address
|
||||||
int curadr; //Current Address
|
int curadr; //Current Address
|
||||||
|
int endadr; //Address after Last Byte
|
||||||
|
int exeadr; //Execution Start Address
|
||||||
int lstadr; //List 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 {int block; char name[MAXLBL+1]; int bytes, value, refrd;};
|
||||||
struct sym symbol; //Current Symbol
|
struct sym symbol; //Current Symbol
|
||||||
struct sym symtbl[MAXSYM]; //Global Symbol Table
|
struct sym symtbl[MAXSYM]; //Global Symbol Table
|
||||||
@ -36,6 +45,7 @@ char cmmnt[MAXSTR]; //Assembly Line Comment
|
|||||||
char mcode[MAXSTR]; //Generated Bytes
|
char mcode[MAXSTR]; //Generated Bytes
|
||||||
char strng[MAXSTR]; //Parsed String
|
char strng[MAXSTR]; //Parsed String
|
||||||
|
|
||||||
|
|
||||||
int opridx; //Index into Operand
|
int opridx; //Index into Operand
|
||||||
char cpdchr; //Last Character Copied into oprnd
|
char cpdchr; //Last Character Copied into oprnd
|
||||||
|
|
||||||
@ -67,8 +77,13 @@ FILE *incfil; //Include File Pointer
|
|||||||
/* Print Usage Info and Exit */
|
/* Print Usage Info and Exit */
|
||||||
void usage(char* appnam) {
|
void usage(char* appnam) {
|
||||||
printf("Usage: %s [opts] asmfile objfile [lstfile]\n", appnam);
|
printf("Usage: %s [opts] asmfile objfile [lstfile]\n", appnam);
|
||||||
printf(" Opts: -p - Commodore PRG format\n");
|
printf(" Opts: -d - Output debug info\n");
|
||||||
printf(" -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);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,15 +120,18 @@ void xerror(char* format, char *s) {
|
|||||||
/* Open File with Error Checking */
|
/* Open File with Error Checking */
|
||||||
FILE * opnfil(char* name, char* mode, char* path) {
|
FILE * opnfil(char* name, char* mode, char* path) {
|
||||||
if (debug) printf("Opening file '%s' with mode '%s'\n", name, mode);
|
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);
|
FILE *fp = fopen(name, mode);
|
||||||
if (!fp) {
|
if (!fp) {
|
||||||
char spec[256];
|
char spec[256], paths[256];
|
||||||
char *token = strtok(path, " ");
|
strcpy(paths, path);
|
||||||
while (token) {
|
char *token = strtok(paths, " ");
|
||||||
strcpy(spec, path); strcat(spec, "\\"); strcat(spec, name);
|
while (token != NULL) {
|
||||||
|
strcpy(spec, token); strcat(spec, "\\"); strcat(spec, name);
|
||||||
if (debug) printf("Opening file \"%s\" with mode \"%s\"\n", spec, mode);
|
if (debug) printf("Opening file \"%s\" with mode \"%s\"\n", spec, mode);
|
||||||
fp = fopen(spec, mode); if (fp) break;
|
fp = fopen(spec, mode); if (fp) break;
|
||||||
token = strtok(NULL, " ");
|
token = strtok(NULL, " ");
|
||||||
|
if (debug) printf("token = \"%s\"\n", token);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!fp) xerror("Error Opening File '%s'\n", name);
|
if (!fp) xerror("Error Opening File '%s'\n", name);
|
||||||
@ -121,6 +139,17 @@ FILE * opnfil(char* name, char* mode, char* path) {
|
|||||||
return fp;
|
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 *
|
/* Skip Character in Input Line *
|
||||||
* Args: c - Character to Skip *
|
* Args: c - Character to Skip *
|
||||||
* Updates: linptr */
|
* Updates: linptr */
|
||||||
@ -205,11 +234,16 @@ int plabel(void) {
|
|||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Append to Operand */
|
||||||
|
void aoprnd(int c) {
|
||||||
|
if (opridx < MAXSTR) oprnd[opridx++] = toupper(c);
|
||||||
|
}
|
||||||
|
|
||||||
/* Copy Character to Operand and Increment */
|
/* Copy Character to Operand and Increment */
|
||||||
int cpychr(int c) {
|
int cpychr(int c) {
|
||||||
if (c && toupper(*linptr) != c) return FALSE;
|
if (c && toupper(*linptr) != c) return FALSE;
|
||||||
cpdchr = *linptr;
|
cpdchr = *linptr;
|
||||||
if (opridx < MAXSTR) oprnd[opridx++] = toupper(cpdchr);
|
aoprnd(cpdchr);
|
||||||
linptr++;
|
linptr++;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@ -324,11 +358,66 @@ int evlopd(int maxsiz) {
|
|||||||
return result;
|
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 */
|
/* Write Byte to Output File */
|
||||||
void outbyt(int b) {
|
void outbyt(int b) {
|
||||||
if (curadr > -1) curadr++;
|
if (curadr > -1) curadr++;
|
||||||
if (passno != 2) return;
|
if (passno != 2) return;
|
||||||
fputc(b & 0xFF, outfil);
|
if (objbin) fputc(b & 0xFF, outfil);
|
||||||
|
else outtxt(b);
|
||||||
sprintf(bytstr, "%02X ", b);
|
sprintf(bytstr, "%02X ", b);
|
||||||
if (strlen(mcode) < 9) strcat(mcode, bytstr);
|
if (strlen(mcode) < 9) strcat(mcode, bytstr);
|
||||||
}
|
}
|
||||||
@ -339,6 +428,20 @@ void outwrd(int w) {
|
|||||||
outbyt(w >> 8);
|
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 */
|
/* Lookup Opcode */
|
||||||
int lkpopc(struct opc opl[]) {
|
int lkpopc(struct opc opl[]) {
|
||||||
if (debug) printf("Looking up Mnemonic %s\n", mnmnc);
|
if (debug) printf("Looking up Mnemonic %s\n", mnmnc);
|
||||||
@ -403,15 +506,23 @@ void asmequ(void) {
|
|||||||
setsym(evlopd(0xFFFF), 0);
|
setsym(evlopd(0xFFFF), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Assemble EXE Pseudo-Op */
|
||||||
|
void asmexe(void) {
|
||||||
|
exeadr = evlopd(0xFFFF);
|
||||||
|
}
|
||||||
|
|
||||||
/* Assemble ORG Pseudo-Op */
|
/* Assemble ORG Pseudo-Op */
|
||||||
void asmorg(void) {
|
void asmorg(void) {
|
||||||
orgadr = evlopd(0xFFFF);
|
orgadr = evlopd(0xFFFF);
|
||||||
|
if (exeadr < 0) exeadr = orgadr;
|
||||||
if (passno == 1 && symbol.name[0]) {
|
if (passno == 1 && symbol.name[0]) {
|
||||||
symbol.value = orgadr;
|
symbol.value = orgadr;
|
||||||
symbol.bytes = 2;
|
symbol.bytes = 2;
|
||||||
}
|
}
|
||||||
if (passno == 2 && objtyp == PRGFIL)
|
if (passno == 2 ) {
|
||||||
outwrd(orgadr);
|
if (objtyp == PRGFIL) outwrd(orgadr);
|
||||||
|
if (objtyp == ATRFIL) atrhdr(orgadr, lstadr);
|
||||||
|
}
|
||||||
curadr = orgadr;
|
curadr = orgadr;
|
||||||
lstadr = orgadr;
|
lstadr = orgadr;
|
||||||
}
|
}
|
||||||
@ -473,6 +584,7 @@ int asmpso(int dot) {
|
|||||||
case 'M': asmens(); break; //ENDSubroutine
|
case 'M': asmens(); break; //ENDSubroutine
|
||||||
case 'I': asminf(); break; //INCLude
|
case 'I': asminf(); break; //INCLude
|
||||||
case '*': asmorg(); break; //ORG
|
case '*': asmorg(); break; //ORG
|
||||||
|
case 'X': asmexe(); break; //EXEC
|
||||||
case 'P': asmprc(); break; //PROCessor
|
case 'P': asmprc(); break; //PROCessor
|
||||||
case 'E': asmend(); break; //END
|
case 'E': asmend(); break; //END
|
||||||
case 'A': asmaln(); break; //ALIGn
|
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 */
|
/* Assemble Opcode */
|
||||||
int asmopc(int dot) {
|
int asmopc(int dot) {
|
||||||
opmod = 0;
|
opmod = 0;
|
||||||
if (asmpso(dot)) return TRUE; //Check For/Assemble Pseudo-Op
|
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 (lkpopc(opclst) == FALSE) xerror("Invalid Mnemonic %s\n", mnmnc);
|
||||||
if (debug) printf("Assembling Opcode Token 0x%02X, ", token);
|
if (debug) printf("Assembling Opcode Token 0x%02X, ", token);
|
||||||
if (debug) printf("Addressing Mode Mask 0x%04X\n", amode);
|
if (debug) printf("Addressing Mode Mask 0x%04X\n", amode);
|
||||||
skpspc();
|
skpspc();
|
||||||
if (amode == RELTV) asmbrn(TRUE); //Branch (Relative) Instruction
|
if (amode == RELTV) asmbrn(TRUE); //Branch (Relative) Instruction
|
||||||
else if (amode == 0x0004 || amode == 0x1004) asmzpr(); //Branch (Relative) Instruction
|
else if (amode == 0x0004 || amode == 0x1004) asmzpr(); //Branch ZP (Relative)
|
||||||
else if (cpychr('#')) asmimd(); //Assemble Implied Instruction
|
else if (cpychr('#')) asmimd(); //Assemble Immediate Instruction
|
||||||
else if (cpychr('(')) asmind(); //Assemble Indirect Instruction
|
else if (cpychr('(')) asmind(); //Assemble Indirect Instruction
|
||||||
else asmiaz(); //Assemble Implied/Accumulator/Absolute/ZeroPage Instruction
|
else asmiaz(); //Assemble Implied/Accumulator/Absolute/ZeroPage Instruction
|
||||||
if (debug) dbgopc();
|
if (debug) dbgopc();
|
||||||
@ -685,6 +856,13 @@ void clsinc(void) {
|
|||||||
endasm = FALSE; //Clear End Flag for Return to Main File
|
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) *
|
/* Assemble Input File (Two Pass) *
|
||||||
* Args: pass - Assembly Pass (1 or 2) *
|
* Args: pass - Assembly Pass (1 or 2) *
|
||||||
* Requires: inpfil - Input File Pointer *
|
* Requires: inpfil - Input File Pointer *
|
||||||
@ -699,6 +877,8 @@ void asmfil(int pass) {
|
|||||||
blknum = 0; // and Local Block Number
|
blknum = 0; // and Local Block Number
|
||||||
orgadr = -1; //Origin Address Not Set
|
orgadr = -1; //Origin Address Not Set
|
||||||
curadr = orgadr; //Set Current Address to Origin
|
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");
|
if (debug) printf("Rewinding Input File\n");
|
||||||
rewind(inpfil); //Start at Beginning of Input File
|
rewind(inpfil); //Start at Beginning of Input File
|
||||||
while (TRUE) {
|
while (TRUE) {
|
||||||
@ -720,6 +900,8 @@ void asmfil(int pass) {
|
|||||||
lineno++;
|
lineno++;
|
||||||
if (incnam[0] && incfil == NULL) opninc(); //Open Include File
|
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 */
|
/* Parse Command Line Option */
|
||||||
@ -729,9 +911,14 @@ int pcoptn(char *argval) {
|
|||||||
if (debug) printf(" Option '%c'\n", option);
|
if (debug) printf(" Option '%c'\n", option);
|
||||||
switch(option) {
|
switch(option) {
|
||||||
case 'D': debug = TRUE; break; //Enable debug Output
|
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 '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);
|
default: xerror("Illegal Command Line Option %s\n", argval);
|
||||||
}
|
}
|
||||||
|
if (debug && objtyp) printf("Object type set to %d\n", objtyp);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -766,12 +953,13 @@ int main(int argc, char *argv[]) {
|
|||||||
objtyp = BINFIL; //Default Object File Type to Binary
|
objtyp = BINFIL; //Default Object File Type to Binary
|
||||||
pcargs(argc, argv); //Parse Command Line Arguments
|
pcargs(argc, argv); //Parse Command Line Arguments
|
||||||
inpfil = opnfil(inpnam, "r", ""); //Open Input File
|
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
|
if (lstnam[0]) //If List File Name Specified
|
||||||
lstfil = opnfil(lstnam, "w", ""); // Open List File
|
lstfil = opnfil(lstnam, "w", ""); // Open List File
|
||||||
asmfil(1); //Assemble Input File (First Pass)
|
asmfil(1); //Assemble Input File (First Pass)
|
||||||
asmfil(2); //Assemble Input File (First Pass)
|
asmfil(2); //Assemble Input File (First Pass)
|
||||||
if (lstfil && symcnt) prtsym(); //Print Symbol Table
|
if (lstfil && symcnt) prtsym(); //Print Symbol Table
|
||||||
|
clsobj(); //Close Object File
|
||||||
exit(0); //Exit with No Errors
|
exit(0); //Exit with No Errors
|
||||||
}
|
}
|
||||||
|
|
||||||
|
33
a02.h
33
a02.h
@ -4,15 +4,18 @@
|
|||||||
#define MAXLBL 8 //Maximum Symbol Length
|
#define MAXLBL 8 //Maximum Symbol Length
|
||||||
#define MAXSYM 1024 //Maximum Number of Labels
|
#define MAXSYM 1024 //Maximum Number of Labels
|
||||||
|
|
||||||
|
//#define NULL &0
|
||||||
|
|
||||||
#define FALSE 0
|
#define FALSE 0
|
||||||
#define TRUE -1
|
#define TRUE -1
|
||||||
|
|
||||||
/* Address Mode Bit Masks */
|
/* Address Mode Bit Masks */
|
||||||
|
#define RGSTR 0x0000 //Register (Sweet 16)
|
||||||
#define ACMLT 0x0001 //Accumulator [$xA]
|
#define ACMLT 0x0001 //Accumulator [$xA]
|
||||||
#define IMMDT 0x0002 //*Immediate [w/Acc]
|
#define IMMDT 0x0002 //*Immediate [w/Acc]
|
||||||
#define ZPAGE 0x0004 //Zero Page
|
#define ZPAGE 0x0004 //Zero Page
|
||||||
#define ZPAGX 0x0008 //*Zero Page,X
|
#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 ABSLT 0x0020 //Absolute
|
||||||
#define ABSLX 0x0040 //*Absolute,X [fixops()]
|
#define ABSLX 0x0040 //*Absolute,X [fixops()]
|
||||||
#define ABSLY 0x0080 //Absolute,Y
|
#define ABSLY 0x0080 //Absolute,Y
|
||||||
@ -24,13 +27,15 @@
|
|||||||
|
|
||||||
char zpgabs[][9] = {"Absolute", "ZeroPage"};
|
char zpgabs[][9] = {"Absolute", "ZeroPage"};
|
||||||
|
|
||||||
|
/* Address Mode Descriptions */
|
||||||
struct amd {int amode; char desc[12];};
|
struct amd {int amode; char desc[12];};
|
||||||
struct amd amdesc[] = {
|
struct amd amdesc[] = {
|
||||||
{ACMLT, "Accumulator"},
|
{ACMLT, "Accumulator"},
|
||||||
{IMMDT, "Immediate"},
|
{IMMDT, "Immediate"},
|
||||||
{ZPAGE, "Zero Page"},
|
{ZPAGE, "Zero Page"},
|
||||||
{ZPAGX, "Zero Page,X"},
|
{ZPAGX, "Zero Page,X"},
|
||||||
{ABSLT, "Absolute"},
|
{ABSLT, "Absolute"},
|
||||||
|
{RGSTR, "Register"},
|
||||||
{ABSLX, "Absolute,X"},
|
{ABSLX, "Absolute,X"},
|
||||||
{ABSLY, "Absolute,Y"},
|
{ABSLY, "Absolute,Y"},
|
||||||
{IMPLD, "Implied"},
|
{IMPLD, "Implied"},
|
||||||
@ -45,7 +50,8 @@ struct opc {char name[5], token; int amode;};
|
|||||||
struct opc psolst[] = {
|
struct opc psolst[] = {
|
||||||
{"BYTE", 'B', 0}, {"HEX", 'H'}, {"WORD", 'W', 0}, {"EQU", '=', 0}, {"FILL", 'F', 0},
|
{"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},
|
{"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[] = {
|
struct opc opclst[] = {
|
||||||
@ -73,7 +79,7 @@ struct opc opclst[] = {
|
|||||||
{"RMB4", 0x47, 0x0004}, {"RMB5", 0x57, 0x0004}, {"RMB6", 0x67, 0x0004}, {"RMB7", 0x77, 0x0004},
|
{"RMB4", 0x47, 0x0004}, {"RMB5", 0x57, 0x0004}, {"RMB6", 0x67, 0x0004}, {"RMB7", 0x77, 0x0004},
|
||||||
{"SMB0", 0x87, 0x0004}, {"SMB1", 0x97, 0x0004}, {"SMB2", 0xA7, 0x0004}, {"SMB3", 0xB7, 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},
|
{"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},
|
{"BBR0", 0x0F, 0x1004}, {"BBR1", 0x1F, 0x1004}, {"BBR2", 0x2F, 0x1004}, {"BBR3", 0x3F, 0x1004},
|
||||||
{"BBR4", 0x4F, 0x1004}, {"BBR5", 0x5F, 0x1004}, {"BBR6", 0x6F, 0x1004}, {"BBR7", 0x7F, 0x1004},
|
{"BBR4", 0x4F, 0x1004}, {"BBR5", 0x5F, 0x1004}, {"BBR6", 0x6F, 0x1004}, {"BBR7", 0x7F, 0x1004},
|
||||||
@ -113,3 +119,22 @@ struct opf opfix[] = {
|
|||||||
{0,0,0}
|
{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}
|
||||||
|
};
|
||||||
|
@ -1,11 +1,32 @@
|
|||||||
; C02 module intlib.h02 assembly language subroutines
|
; C02 module intlib.h02 assembly language subroutines
|
||||||
; Requires
|
; Requires external zero page words DSTPTR, SRCPTR,
|
||||||
; external zero page words DSTPTR and SRCPTR
|
; external bytes TEMP0, TEMP1, TEMP2, and TEMP3, and
|
||||||
; and external locations TEMP0, TEMP1, TEMP2, and TEMP3
|
; external words INTACC, INTARG, and INTOVR.
|
||||||
|
|
||||||
|
|
||||||
SUBROUTINE INTLIB
|
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
|
;Args: Y,X = Integer to get Absolute Value Of
|
||||||
;Sets: TEMP1, TEMP2
|
;Sets: TEMP1, TEMP2
|
||||||
;Affects: C, N, Z
|
;Affects: C, N, Z
|
||||||
@ -23,188 +44,248 @@ IABS: CPY #$80 ;If Negative (High Bit Set)
|
|||||||
|
|
||||||
;imax(i) - Get MAXimum of Two Integers
|
;imax(i) - Get MAXimum of Two Integers
|
||||||
;Args: Y,X = Second Integer
|
;Args: Y,X = Second Integer
|
||||||
;Uses: SRCPTR = First Integer
|
;Uses: INTACC = First Integer
|
||||||
;Affects: N,Z,C
|
;Affects: N,Z,C
|
||||||
;Returns: Y,X = Larger of the Two Arguments
|
;Returns: Y,X = Larger of the Two Arguments
|
||||||
IMAX: CPY SRCPTR+1 ;If Y < SRCPTR MSB
|
IMAX: CPY INTACC+1 ;If Y < INTACC MSB
|
||||||
BCC .GETSRC ; Return SRCPTR
|
BCC .GETACC ; Return INTACC
|
||||||
CPX SRCPTR ;IF X >= SRCPTR LSB
|
CPX INTACC ;IF X >= INTACC LSB
|
||||||
BCS .RETURN ; Return Argument
|
BCS .IMSET ; Set INTACC to and Return Argument
|
||||||
.GETSRC JMP GETSRC ;Return Integer in SRCPTR
|
.GETACC LDX INTACC ;Return Integer Accumulator
|
||||||
|
LDY INTACC+1
|
||||||
|
RTS
|
||||||
|
|
||||||
;imin(i) - Get MINimum of Two Integers
|
;imin(i) - Get MINimum of Two Integers
|
||||||
;Args: Y,X = Second Integer
|
;Args: Y,X = Second Integer
|
||||||
;Uses: SRCPTR = First Integer
|
;Uses: INTACC = First Integer
|
||||||
|
;Sets: IINTACC = Result
|
||||||
;Affects: N,Z,C
|
;Affects: N,Z,C
|
||||||
;Returns: Y,X = Larger of the Two Arguments
|
;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
|
BCC .RETURN ; Return Argument
|
||||||
BNE .GETSRC ;If Y > SRCPTR+1 Return SRCPTR
|
BNE .GETACC ;If Y > INTACC+1
|
||||||
CPX SRCPTR ;If X >= SRCPTR
|
CPX INTACC ;or X >= INTACC
|
||||||
BCS .GETSRC ; Return SRCPTR
|
BCS .GETACC ; Return INTACC
|
||||||
RTS ;Return Argument
|
.IMSET JMP IACC ;Else Set INTACC to and Return Argument
|
||||||
|
|
||||||
;iaddc(c,i) - Add Byte c to Integer i
|
;iaddc(c,i) - Integer ADD Char c to int i
|
||||||
IADDC: JSR SETSRC ;Save Integer and Clear Y
|
IADDC: JSR IACC ;Store Integer in Accumulator
|
||||||
|
LDY #0 ;Set Argument MSB to 0
|
||||||
TAX ;Copy Byte to LSB and drop into IADD
|
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
|
;Args: Y,X = Addend
|
||||||
;Requires: setsrc(g) - Augend
|
;Requires: IACC(g) - Augend
|
||||||
;Sets: TEMP1,TEMP2 = Addend
|
;Sets: INTACC = Result
|
||||||
;Affects: Z,C
|
;Affects: Z
|
||||||
;Returns: A = Carry
|
;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
|
; Y,X = Sum
|
||||||
; N = Sign of Result
|
; N = Sign of Result
|
||||||
IADD: CLC ;Clear Carry for Addition
|
IADD: CLC ;Clear Carry for Addition
|
||||||
TXA ;Add Addend LSB
|
TXA ;Add Addend LSB
|
||||||
ADC SRCPTR ;to Augend LSB
|
ADC INTACC ;to Augend LSB
|
||||||
TAX ;and Copy to X
|
TAX ;and Copy to X
|
||||||
TYA ;Add Addend MSB
|
TYA ;Add Addend MSB
|
||||||
ADC SRCPTR+1 ;to Augebd MSB
|
ADC INTACC+1 ;to Augebd MSB
|
||||||
TAY ;and Copy to Y
|
TAY ;and Copy to Y
|
||||||
LDA #0 ;Set Overflow to 0
|
PHP ;Save Result Flags
|
||||||
ROL ; Rotate Carry (Same as Adding it)
|
LDA #0 ;Clear CHR Result to 0
|
||||||
RTS ; and Return
|
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
|
;Args: Y,X = Subtrahend
|
||||||
;Requires: setsrc(m) - Minuend
|
;Requires: IACC(m) - Minuend
|
||||||
;Sets: TEMP1,TEMP2 = Subtrahend
|
;Sets: INTACC = Difference
|
||||||
;Affects: Z,C
|
; INTARG = Subtrahend
|
||||||
;Returns: A = Carry
|
;Affects: Z
|
||||||
|
;Returns: A,C = Carry
|
||||||
; Y,X = Difference
|
; Y,X = Difference
|
||||||
; N = Sign of Result
|
; N = Sign of Result
|
||||||
ISUB: JSR SAVRXY ;Store Subtrahend in TEMP1,TEMP2
|
ISUB: JSR .SETARG ;Store Subtrahend in INTARG
|
||||||
SEC ;Set Carry for Subtraction
|
SEC ;Set Carry for Subtraction
|
||||||
LDA SRCPTR ;Load Minuend LSB
|
LDA INTACC ;Load Minuend LSB
|
||||||
SBC TEMP1 ;Subtract Subtrahend LSB
|
SBC INTARG ;Subtract Subtrahend LSB
|
||||||
TAX ;Copy Difference LSB to X
|
TAX ;Copy Difference LSB to X
|
||||||
LDA SRCPTR+1 ;Load Minuend MSB
|
LDA INTACC+1 ;Load Minuend MSB
|
||||||
SBC TEMP2 ;Subtract Subtrahend MSB
|
SBC INTARG+1 ;Subtract Subtrahend MSB
|
||||||
TAY ;Copy Difference MSB to Y
|
TAY ;Copy Difference MSB to Y
|
||||||
LDA #0 ;Set Overflow Byte to 0
|
PHP ;Save Result Flags
|
||||||
SBC #0 ; Subtract Carry
|
LDA #0 ;Set Overflow Byte to 0
|
||||||
RTS ; and Return
|
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
|
;imult(m) = MULTiply Integer n * Integer m
|
||||||
;Args: Y,X - Multiplier
|
;Args: Y,X = Multiplier
|
||||||
;Requires: DSTPTR = Multiplicand
|
;Uses: INTACC = Multiplicand
|
||||||
;Sets: TEMP0-TEMP3 = 32 Bit Product
|
;Sets: INTACC = Product MSB, LSB
|
||||||
;Destroys: SRCPTR
|
;Sets: INTOVR = Product MSB, LSB
|
||||||
;Affects: A,C,Z,N
|
;Destroys: TEMP0,TEMP1,TEMP2,TEMP3
|
||||||
|
;Affects: C,Z,N
|
||||||
;Returns: A,Y,X = 24 Bit Product
|
;Returns: A,Y,X = 24 Bit Product
|
||||||
IMULT: JSR SETSRC ;Save Multiplier
|
IMULT: JSR .SETARG ;Save Multiplier
|
||||||
STY TEMP0+2 ;Clear Upper Bits of Product
|
LDY #0
|
||||||
STY TEMP0+3
|
STY INTOVR ;Clear Upper Bits of Product
|
||||||
|
STY INTOVR+1
|
||||||
LDX #16 ;Rotate Through 16 Bits
|
LDX #16 ;Rotate Through 16 Bits
|
||||||
.MSHFTR LSR SRCPTR+1 ;Divide Multiplier by 2
|
.MSHFTR LSR INTARG+1 ;Divide Multiplier by 2
|
||||||
ROR SRCPTR
|
ROR INTARG
|
||||||
BCC .MROTR ;If Shifted out Bit is 1
|
BCC .MROTR ;If Shifted out Bit is 1
|
||||||
LDA TEMP0+2 ; Add Multiplicand
|
LDA INTACC ; Add Multiplicand
|
||||||
CLC ; to Upper Half of Product
|
CLC ; to Upper Half of Product
|
||||||
ADC DSTPTR
|
ADC INTOVR
|
||||||
STA TEMP0+2
|
STA INTOVR
|
||||||
LDA TEMP0+3
|
LDA INTOVR+1
|
||||||
ADC DSTPTR+1
|
ADC INTACC+1
|
||||||
STA TEMP0+3
|
STA INTOVR+1
|
||||||
.MROTR ROR TEMP0+3
|
.MROTR ROR INTOVR+1
|
||||||
ROR TEMP0+2
|
ROR INTOVR
|
||||||
ROR TEMP0+1
|
ROR TEMP1
|
||||||
ROR TEMP0
|
ROR TEMP0
|
||||||
DEX ;Decrement Counter
|
DEX ;Decrement Counter
|
||||||
BNE .MSHFTR ;and Process Next Bit
|
BNE .MSHFTR ;and Process Next Bit
|
||||||
LDX TEMP0
|
LDA INTOVR ;Get Bits 16-24 of Result
|
||||||
LDY TEMP1 ;Return Low 24 Bits of
|
LDY TEMP1 ;Get Bits 8-15 of Result
|
||||||
LDA TEMP2 ;Product in A, Y, and X
|
LDX TEMP0 ;Get Bits 0-7 of Result
|
||||||
RTS
|
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
|
;Args: Y,X - Divisor
|
||||||
;Requires: DSTPTR = Dividend
|
;Requires: IACC(d) = Dividend
|
||||||
;Sets: SRCPTR = Divisor
|
;Sets: INTARG = Divisor
|
||||||
; DSTPTR = Quotient
|
; INTACC, INTOVR = Modulus
|
||||||
; TEMP1,TEMP2 = Remainder
|
;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
|
;Affects: A,C,Z,N
|
||||||
;Returns: Y,X = 16 Bit Quotient
|
;Returns: Y,X = 16 Bit Quotient
|
||||||
IDIV: JSR .IDIV ;Do Division and
|
IDIV: JSR .SETARG ;Save Divisor
|
||||||
JMP GETDST ;Return Quotient
|
LDY #0
|
||||||
|
STY INTOVR
|
||||||
;imod(d) - Integer MODulus
|
STY INTOVR+1
|
||||||
;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
|
|
||||||
LDX #16 ;repeat for each bit: ...
|
LDX #16 ;repeat for each bit: ...
|
||||||
.IDLOOP ASL DSTPTR ;dividend lb & hb*2, msb -> Carry
|
.IDLOOP ASL INTACC ;dividend lb & hb*2, msb -> Carry
|
||||||
ROL DSTPTR+1
|
ROL INTACC+1
|
||||||
ROL TEMP1 ;remainder lb & hb * 2 + msb from carry
|
ROL INTOVR ;remainder lb & hb * 2 + msb from carry
|
||||||
ROL TEMP1+1
|
ROL INTOVR+1
|
||||||
LDA TEMP1
|
LDA INTOVR
|
||||||
SEC
|
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
|
TAY ;lb result -> Y, for we may need it later
|
||||||
LDA TEMP1+1
|
LDA INTOVR+1
|
||||||
SBC SRCPTR+1
|
SBC INTARG+1
|
||||||
BCC .IDSKIP ;if carry=0 then divisor didn't fit in yet
|
BCC .IDSKIP ;if carry=0 then divisor didn't fit in yet
|
||||||
STA TEMP1+1 ;else save substraction result as new remainder,
|
STA INTOVR+1 ;else save substraction result as new remainder,
|
||||||
STY TEMP1
|
STY INTOVR
|
||||||
INC DSTPTR ;and INCrement result cause divisor fit in 1 times
|
INC INTACC ;and INCrement result cause divisor fit in 1 times
|
||||||
.IDSKIP DEX
|
.IDSKIP DEX
|
||||||
BNE .IDLOOP
|
BNE .IDLOOP
|
||||||
RTS
|
JMP .GETACC ;Return Integer Accumulator
|
||||||
|
|
||||||
;ishftl(n,i) - Shift Integer i to the Left n Bits
|
;ishftl(n,i) - Shift Integer i to the Left n Bits
|
||||||
;Sets: TEMP1, TEMP2 = LSB, MSB of Result
|
;Args: A = Number of Bits to Shift
|
||||||
;Affects: A,Y,N,Z,C
|
; Y,X = Integer Value to Shift
|
||||||
;Returns: A = Bits Shifted out of Integer
|
;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
|
; Y,X = Shifted Integer
|
||||||
ISHFTL: JSR SAVRXY ;Save X,Y in TEMP1,TEMP2
|
ISHFTL: JSR IACC ;Save Argument in INTACC
|
||||||
TAY ;Set Counter to Number of Bits
|
LDX #0 ;Clear Overflow
|
||||||
BEQ .RESRXY ;If Zero, Return
|
STX INTOVR
|
||||||
LDA #0 ;Clear Overflow
|
STX INTOVR
|
||||||
.LSLOOP ASL TEMP1 ;Shift LSB to Left
|
TAX ;Set Counter to Number of Bits
|
||||||
ROL TEMP2 ;Rotate MSB to Left
|
BEQ .LSDONE ;If Zero, Return 0
|
||||||
ROL ;Rotate Carry into A
|
.LSLOOP ASL INTACC ;Shift Bits 0-7 to Left
|
||||||
DEY ;Decrement Counter
|
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
|
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
|
;ishftr(n,i) - Shift Integer i to the Right n Bits
|
||||||
;Sets: TEMP1, TEMP2 = LSB, MSB of Result
|
;Args: A = Number of Bits to Shift
|
||||||
;Affects: A,Y,N,Z,C
|
; Y,X = Integer Value to Shift
|
||||||
;Returns: A = Bits Shifted out of Integer
|
;Sets: INTACC = Bits 0 to 15 of Result
|
||||||
; Y,X = Shifted Integer
|
; INTOVR = Bits -1 to -16 of Result
|
||||||
ISHFTR: JSR SAVRXY ;Save X,Y in TEMP1,TEMP2
|
;Sets: INTACC = Shifted Intger
|
||||||
TAY ;Set Counter to Number of Bits
|
;Affects: N,Z,C
|
||||||
BEQ .RESRXY ;If Zero, Return
|
;Returns: A = MSB of Underflow
|
||||||
LDA #0 ;Clear Overflow
|
; Y,X = Shifted Result
|
||||||
.RSLOOP LSR TEMP2 ;Shift MSB to Right
|
ISHFTR: JSR IACC ;Save Argument in INTACC
|
||||||
ROR TEMP1 ;Rotate LSB to Right
|
LDX #0 ;Clear Overflow
|
||||||
ROR ;Rotate Carry into A
|
STX INTOVR
|
||||||
DEY ;Decrement Counter
|
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
|
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
|
;atoi(&s) - ASCII string TO Integer
|
||||||
;Args: Y,X = Address of String to Convert
|
;Args: Y,X = Address of String to Convert
|
||||||
;Sets: TEMP1, TEMP2 = Integer Value
|
;Sets: INTACC = Integer Value
|
||||||
;Affects: TEMP0
|
;Affects: TEMP0,TEMP1,TEMP2
|
||||||
;Returns: A = Number of Digits
|
;Returns: A = Number of Digits
|
||||||
; Y,X = Integer Value
|
; Y,X = Integer Value
|
||||||
ATOI: JSR SETSRC ;Initialize Source String
|
ATOI: JSR SETSRC ;Initialize Source String
|
||||||
STY TEMP1 ;Initialize Result
|
STY TEMP1 ;Initialize Result
|
||||||
STY TEMP2
|
STY TEMP2
|
||||||
.AILOOP LDA (SRCPTR),Y ;Get Next Character
|
.AILOOP LDA (SRCPTR),Y ;Get Next Character
|
||||||
CMP #$30 ;If Less Than '0'
|
CMP #$30 ;If Less Than '0'
|
||||||
BCC .AIDONE ; Exit
|
BCC .AIDONE ; Exit
|
||||||
CMP #$3A ;If Greater Than '9'
|
CMP #$3A ;If Greater Than '9'
|
||||||
@ -235,14 +316,18 @@ ATOI: JSR SETSRC ;Initialize Source String
|
|||||||
INY ;Increment Index
|
INY ;Increment Index
|
||||||
BPL .AILOOP ; and Loop
|
BPL .AILOOP ; and Loop
|
||||||
.AIDONE TYA ;Return Number of Digits
|
.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
|
;itoa(&d) - Integer TO ASCII string
|
||||||
;Args: Y,X = Integer Value to Convert
|
;Args: Y,X = Address of Destination String
|
||||||
|
;Uses: INTACC = Integer to Convert
|
||||||
;Uses: DSTPTR = Destination String
|
;Uses: DSTPTR = Destination String
|
||||||
;Affects: X
|
;Affects: X
|
||||||
;Returns: A,Y = Length of String
|
;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
|
LDY #0 ;Initialize Index into String
|
||||||
STY TEMP3
|
STY TEMP3
|
||||||
.ITOAA LDY #4 ;Set Initial Digit Number
|
.ITOAA LDY #4 ;Set Initial Digit Number
|
||||||
@ -250,24 +335,25 @@ ITOA: JSR CVIBCD ;Convert Integer to Packed BCD
|
|||||||
BNE .IASKIP ;If Zero
|
BNE .IASKIP ;If Zero
|
||||||
DEY ; Decrement Digit Number
|
DEY ; Decrement Digit Number
|
||||||
BNE .IAZERO ; If Not Zero Loop
|
BNE .IAZERO ; If Not Zero Loop
|
||||||
BEQ .IASKIP ; Else .IDSKIP Unpack
|
BEQ .IASKIP ; Else Branch into .IALOOP
|
||||||
.IALOOP JSR UPBCDI ;Unpack Digit #Y
|
.IALOOP JSR UPBCDI ;Unpack Digit #Y
|
||||||
.IASKIP TAX ;Save Digit in X
|
.IASKIP TAX ;Save Digit in X
|
||||||
TYA ;Push Digit Number into Stack
|
TYA ;Push Unpack Index into Stack
|
||||||
PHA
|
PHA
|
||||||
TXA ;and Restore Digit
|
TXA ;and Restore Digit
|
||||||
LDY TEMP3 ;Get Index into String
|
|
||||||
ORA #$30 ;Convert Digit to ASCII
|
ORA #$30 ;Convert Digit to ASCII
|
||||||
|
LDY TEMP3 ;Get Index into String
|
||||||
STA (DSTPTR),Y ;and Store in String
|
STA (DSTPTR),Y ;and Store in String
|
||||||
INC TEMP3 ;Increment Index into String
|
INC TEMP3 ;Increment Index into String
|
||||||
PLA ;Pull Digit Number off Stack
|
PLA ;Pull Digit Number off Stack
|
||||||
TAY
|
TAY
|
||||||
DEY ;Decrement Digit Number
|
DEY ;Decrement Digit Number
|
||||||
BPL .IALOOP ;Loop if >= Zero
|
BPL .IALOOP ;Loop if >= Zero
|
||||||
LDA #0 ;Terminate String
|
LDA #0 ;Terminate String
|
||||||
STA (DSTPTR),Y
|
STA (DSTPTR),Y
|
||||||
TYA ;Return String Length
|
TYA ;Return String Length
|
||||||
RTS
|
JMP .GETACC ;and INTACC
|
||||||
|
|
||||||
|
|
||||||
;upbcdi() - UnPack digits from BCD Integer
|
;upbcdi() - UnPack digits from BCD Integer
|
||||||
; Assumes that TEMP0, TEMP1, and TEMP2
|
; Assumes that TEMP0, TEMP1, and TEMP2
|
||||||
@ -298,21 +384,17 @@ UPBCDI: PHP
|
|||||||
; TEMP1 = Thousands and Hundreds Digit
|
; TEMP1 = Thousands and Hundreds Digit
|
||||||
; TEMP2 = Ten-Thousands Digit
|
; TEMP2 = Ten-Thousands Digit
|
||||||
;Affects: A
|
;Affects: A
|
||||||
CVIBCD: LDA #0 ;Clear BCD Bytes
|
CVIBCD: JSR IACC ;Store Argument
|
||||||
|
LDA #0 ;Clear BCD Bytes
|
||||||
STA TEMP0
|
STA TEMP0
|
||||||
STA TEMP1
|
STA TEMP1
|
||||||
STA TEMP2
|
STA TEMP2
|
||||||
PHP ;Save Status Register
|
PHP ;Save Status Register
|
||||||
SEI ;Disable Interrupts
|
SEI ;Disable Interrupts
|
||||||
SED ;Set Decimal Mode
|
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
|
LDY #16 ;Process 16 bits of Binary
|
||||||
.CVLOOP ASL $101,X ;Shift High Bit Into Carry
|
.CVLOOP ASL INTACC ;Shift High Bit Into Carry
|
||||||
ROL $102,X
|
ROL INTACC+1
|
||||||
LDA TEMP0 ;Add 6 Digit BCD Number Itself
|
LDA TEMP0 ;Add 6 Digit BCD Number Itself
|
||||||
ADC TEMP0 ; Effectively Multiplying It by 2
|
ADC TEMP0 ; Effectively Multiplying It by 2
|
||||||
STA TEMP0 ; and Adding in the Shifted Out Bit
|
STA TEMP0 ; and Adding in the Shifted Out Bit
|
||||||
@ -324,9 +406,27 @@ CVIBCD: LDA #0 ;Clear BCD Bytes
|
|||||||
STA TEMP2
|
STA TEMP2
|
||||||
DEY ;Decrement Counter and
|
DEY ;Decrement Counter and
|
||||||
BNE .CVLOOP ; Process Next Bit
|
BNE .CVLOOP ; Process Next Bit
|
||||||
PLA ;Restore X and Y Registers
|
|
||||||
PLA
|
|
||||||
PLP ;Restore Status Register
|
PLP ;Restore Status Register
|
||||||
RTS
|
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
|
ENDSUBROUTINE
|
||||||
|
@ -2,77 +2,115 @@
|
|||||||
* intlib - Standard Library Routines for Integer Values *
|
* intlib - Standard Library Routines for Integer Values *
|
||||||
*********************************************************/
|
*********************************************************/
|
||||||
|
|
||||||
/* Integer Absolute Value *
|
/* Set Integer Accumlator *
|
||||||
* Args: int w - Integer to test *
|
* Args: int w - Integer value *
|
||||||
* Returns: int v -Absolute value of w */
|
* 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();
|
char iabs();
|
||||||
|
|
||||||
/* Integer Add *
|
/* Integer Add: g + d *
|
||||||
* Setup: setsrc(g) - Augend *
|
* Setup: iset(g) - Augend *
|
||||||
* Args: int d - Addend *
|
* Args: int d - Addend *
|
||||||
* Returns: char c - Carry *
|
* Sets: iacc, iover = Result *
|
||||||
* int r - Sum */
|
* Returns: char c - Carry *
|
||||||
|
* int r - Sum */
|
||||||
char iadd();
|
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 *
|
/* ASCII to Integer *
|
||||||
* Convert ASCII string to Unsigned Integer *
|
* Convert ASCII string to Unsigned Integer *
|
||||||
* Args: &s - String to Convert *
|
* Args: &s - String to Convert *
|
||||||
|
* Sets: iacc = Result *
|
||||||
* Returns: char n - Number of digits parsed *
|
* Returns: char n - Number of digits parsed *
|
||||||
* int v - Numeric value of string */
|
* int v - Numeric value of string */
|
||||||
char atoi();
|
char atoi();
|
||||||
|
|
||||||
/* Integer to ASCII *
|
/* Integer to ASCII *
|
||||||
* Convert Unsigned Integer to String *
|
* Convert Unsigned Integer to String *
|
||||||
* Setup: setdst(s) - Destination String *
|
* Setup: iset(i) - Unsigned Int to Convert *
|
||||||
* Args: int w - Unsigned Int to Convert *
|
* Args: &s - Destination String *
|
||||||
* Returns: char n - Length of string */
|
* Sets: iacc = Argument *
|
||||||
|
* Returns: char n - Length of string */
|
||||||
void itoa();
|
void itoa();
|
||||||
|
|
||||||
/* Integer Divide *
|
/* Integer unsigned Divide *
|
||||||
* Divide Unsigned Integers *
|
* Aetup: iset (n) - Numerator *
|
||||||
* Aetup: setdst(n) - Numerator *
|
* Args: int d - Denominator *
|
||||||
* Args: int d - Denominator *
|
* Sets: iacc = Quotient *
|
||||||
* Returns: int q - Quotient */
|
* Returns: int q - Quotient */
|
||||||
char idiv();
|
char idiv();
|
||||||
|
|
||||||
/* Integer Maximum *
|
/* Integer unsigned Maximum *
|
||||||
* Return Largest of Two Integers *
|
* Return Largest of Two Integers *
|
||||||
* Requires: setsrc(i) - First Integer *
|
* Setup: iset(i) - First Integer *
|
||||||
* Args: int j - Second Integer *
|
* Args: int j - Second Integer *
|
||||||
|
* Sets: iacc = Result *
|
||||||
* Returns: int m - Greater of the Two */
|
* Returns: int m - Greater of the Two */
|
||||||
char imax();
|
char imax();
|
||||||
|
|
||||||
/* Integer Minimum *
|
/* Integer unsigned Minimum *
|
||||||
* Return smallest of Two Integers *
|
* Return smallest of Two Integers *
|
||||||
* Requires: setsrc(i) - First Integer *
|
* Setup: setsrc(i) - First Integer *
|
||||||
* Args: int j - Second Integer *
|
* Args: int j - Second Integer *
|
||||||
* Returns: int m - Lesser of the Two */
|
* Sets: iacc = Result *
|
||||||
|
* Returns: int m - Lesser of the Two */
|
||||||
char imin();
|
char imin();
|
||||||
|
|
||||||
/* Integer Multiply *
|
/* Integer unsigned Modulo *
|
||||||
* Multiply Unsigned Integers *
|
* Aetup: iset(n) - Numerator *
|
||||||
* Requires: setdst(m) - Muliplicand *
|
* Args: int d - Denominator *
|
||||||
* Args: int r - Multiplier *
|
* Sets: iacc = Result *
|
||||||
* Returns: long p - Product */
|
* 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();
|
char imult();
|
||||||
|
|
||||||
/* Integer Left Shift *
|
/* Integer Multiply Char: c * r *
|
||||||
* Args: char n - Number of Bits *
|
* Args: int c - Multplicand
|
||||||
* int w - Value to Shift *
|
* int r - Multiplier *
|
||||||
* Returns: char v - Overflow Bits *
|
* Sets: iacc, iover = 32 bit Product *
|
||||||
int r - Shifted Integer */
|
* 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();
|
char ishftl();
|
||||||
|
|
||||||
/* Integer Shift Right *
|
/* Integer Shift Right *
|
||||||
* Args: char n - Number of Bits *
|
* Args: char n - Number of Bits *
|
||||||
* int w - Value to Shift *
|
* 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 */
|
int r - Shifted Integer */
|
||||||
char ishftr();
|
char ishftr();
|
||||||
|
|
||||||
/* Integer Subtract *
|
/* Integer Subtract: m - s *
|
||||||
* Requires: setsrc(m) - Minuend *
|
* Setup: iaet(m) - Minuend *
|
||||||
* Args: int s - Subtrahend *
|
* Args: int s - Subtrahend *
|
||||||
* Returns: char c - Carry *
|
* Sets: iacc, iover = result *
|
||||||
* int d - Difference */
|
* Returns: char c - Carry *
|
||||||
|
* int d - Difference */
|
||||||
char isub();
|
char isub();
|
||||||
|
@ -5,48 +5,70 @@ DELKEY EQU $08 ;Delete/Backspace Key (Backspace)
|
|||||||
ESCKEY EQU $1B ;Escape/Stop Key (Escape)
|
ESCKEY EQU $1B ;Escape/Stop Key (Escape)
|
||||||
RTNKEY EQU $0D ;Return/Enter Key (Carriage Return)
|
RTNKEY EQU $0D ;Return/Enter Key (Carriage Return)
|
||||||
|
|
||||||
;Zero Page Locations
|
;Zero Page Variables
|
||||||
SRCPTR EQU $30 ;Source String Pointer
|
; $00-$06 ;Reserved
|
||||||
DSTPTR EQU $32 ;Destination String Pointer
|
|
||||||
BLKPTR EQU $34 ;Block Segment Pointer
|
|
||||||
STKPTR EQU $36 ;Stack Pointer
|
|
||||||
USRPTR EQU $38 ;User Pointer
|
|
||||||
|
|
||||||
XMADDR EQU $3A ;Extended Memory Address
|
XMBANK EQU $07 ;Extended Memory Bank
|
||||||
XMBANK EQU $3C ;Extended Memory Bank
|
XMADDR EQU $08 ;Extended Memory Address
|
||||||
; $3D ;Unused
|
|
||||||
|
|
||||||
RDSEED EQU $3E ;Pseudo-RANDOM Seed
|
SRCPTR EQU $10 ;Source Pointer
|
||||||
RANDOM EQU $3F ;Pseudo-RANDOM Number Storage
|
DSTPTR EQU $12 ;Destination Pointer
|
||||||
|
|
||||||
TEMP0 EQU $40 ;Temporary Storage
|
TEMP0 EQU $14 ;Temporary Storage
|
||||||
TEMP1 EQU $41
|
TEMP1 EQU $15
|
||||||
TEMP2 EQU $42
|
TEMP2 EQU $16
|
||||||
TEMP3 EQU $43
|
TEMP3 EQU $17
|
||||||
TMPPTR EQU $44 ;Temporary Pointer
|
TMPPTR EQU $18 ;Temporary Pointer
|
||||||
|
|
||||||
BLKBGN EQU $46
|
LSTPTR EQU $1A ;List Pointer
|
||||||
BLKEND EQU $48
|
USRPTR EQU $1C ;User Pointer
|
||||||
BLKLEN EQU $4A ;Block Segment Length
|
; $1E ;Reserved
|
||||||
SYSBFP EQU $4B ;Position in System Buffer
|
|
||||||
STKBGN EQU $4C ;Stack Start Address
|
BLKLEN EQU $1F ;Block Segment Length
|
||||||
STKEND EQU $4E ;Stack End Address
|
BLKPTR EQU $20 ;Block Segment Pointer
|
||||||
; $50-$FF ;Free Zero Page for Applications
|
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)
|
SYSBFL EQU 128 ;System Buffer Size (Max String Size)
|
||||||
SYSBFR EQU $0200 ;System Buffer
|
SYSBFR EQU $0200 ;System Buffer
|
||||||
; $0281-$03FF ;Unused
|
; $0281-$03FF ;Unused
|
||||||
|
|
||||||
;Memory Mapped I/O
|
;Emulated BIOS System Calls
|
||||||
_KBHIT EQU $FFF0 ;Is a Key Pressed
|
.GETCH EQU $FFE0 ;-K Read Keyboard
|
||||||
_GETCH EQU $FFF1 ;Read Keyboard (Blocking)
|
.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
|
ORG $0400 ;START at RAM midpoint
|
||||||
|
|
||||||
START: JMP MAIN ;Execute Program
|
START: JMP MAIN ;Execute Program
|
||||||
|
|
||||||
;Read Character from Console
|
;Read Character from Console
|
||||||
GETKEY EQU $FFE0 ;Emulator _GETCH Routine
|
GETKEY EQU .GETCH ;Emulator _GETCH Routine
|
||||||
|
|
||||||
;Poll Character from Keyboard
|
;Poll Character from Keyboard
|
||||||
POLKEY: BRK ;Exit Emulator
|
POLKEY: BRK ;Exit Emulator
|
||||||
@ -58,7 +80,7 @@ GETCHR: JSR GETKEY ;Get Key from Console
|
|||||||
RTS
|
RTS
|
||||||
|
|
||||||
;Read Character from stdin
|
;Read Character from stdin
|
||||||
RDCHAR: LDA $FFEA ;Read Character from STDIN
|
RDCHAR: LDA .STDIO ;Read Character from STDIN
|
||||||
CMP #$FF ;If EOF
|
CMP #$FF ;If EOF
|
||||||
BNE RDCHAX
|
BNE RDCHAX
|
||||||
LDA #0 ; Set to ASCII NUL
|
LDA #0 ; Set to ASCII NUL
|
||||||
@ -80,16 +102,12 @@ NEWLIN: LDA #$0D ;Load Carriage Return into Accumulator
|
|||||||
JMP PUTCHR ; and Print it
|
JMP PUTCHR ; and Print it
|
||||||
|
|
||||||
;Print Character to Console
|
;Print Character to Console
|
||||||
PUTCHR EQU $FFE3 ;Emulator CHROUT Routine
|
PUTCHR EQU .PUTCH ;Emulator CHROUT Routine
|
||||||
|
|
||||||
;Write Character to stdout
|
;Write Character to stdout
|
||||||
PRCHAR: STA $FFEA ;Read Character from STDIN
|
PRCHAR: STA .STDIO ;Read Character from STDIN
|
||||||
RTS
|
RTS
|
||||||
|
|
||||||
EXIT EQU $FFEC ;Emulator SHUTDN Routine
|
|
||||||
|
|
||||||
FSCMD EQU $FFE6 ;run6502 File System Command Routine
|
|
||||||
|
|
||||||
INCLUDE "prbyte.a02" ;PRBYTE and PRHEX routines
|
INCLUDE "prbyte.a02" ;PRBYTE and PRHEX routines
|
||||||
INCLUDE "putstr.a02" ;PUTSTR routine
|
INCLUDE "putstr.a02" ;PUTSTR routine
|
||||||
|
|
||||||
|
@ -1,25 +1,26 @@
|
|||||||
/* run6502 Header File */
|
/* run6502 Header File */
|
||||||
|
|
||||||
/* Platform Specific Settings */
|
/* Platform Specific Settings */
|
||||||
#pragma zeropage $50 $FF //Zero Page Free Space
|
#pragma zeropage $40 $FF //Zero Page Free Space
|
||||||
|
|
||||||
/* Platform Specific Constants */
|
/* Platform Specific Constants */
|
||||||
#define DELKEY $08 //Delete/Backspace Key
|
#define DELKEY $7F //Delete/Backspace Key
|
||||||
#define ESCKEY $1B //Escape/Stop Key
|
#define ESCKEY $1B //Escape/Stop Key
|
||||||
#define RTNKEY $0D //Return/Enter Key
|
#define RTNKEY $0D //Return/Enter Key
|
||||||
#define SYSBFL 128 //System Buffer Length
|
#define SYSBFL 128 //System Buffer Length
|
||||||
|
|
||||||
/* Standard Library Variables */
|
/* Standard Library Variables */
|
||||||
zeropage int srcptr, dstptr; //Source and Destination Pointer
|
zeropage int srcptr, dstptr; //Source and Destination Pointer
|
||||||
zeropage int blkptr, stkptr; //Block and Stack Pointers
|
zeropage int blkptr, stkptr; //Block and Stack Pointers
|
||||||
zeropage int tmpptr, usrptr; //Temporary and User Pointer
|
zeropage int tmpptr, lstptr, usrptr; //Temporary and User Pointer
|
||||||
int stkbgn, stkend; //Stack Begin and End Address
|
int stkbgn, stkend; //Stack Begin and End Address
|
||||||
int blkbgn, blkend; //Block Begin and End Address
|
int blkbgn, blkend; //Block Begin and End Address
|
||||||
char blklen, xmbank; //Block Segment Length, Ext Memory Bank
|
char blklen, xmbank; //Block Segment Length, Ext Memory Bank
|
||||||
int xmaddr; //Extended Memory Address
|
int xmaddr; //Extended Memory Address
|
||||||
char random, rdseed; //Pseudo-Random Number and Seed
|
int intacc, intarg, intovr; //Integer Accumulator, Argument, Overflow
|
||||||
char temp0, temp1, temp2, temp3; //Temporary Storage
|
char random, rdseed; //Pseudo-Random Number and Seed
|
||||||
char sysbfr[], sysbfp; //System String Buffer and Position
|
char temp0, temp1, temp2, temp3; //Temporary Storage
|
||||||
|
char sysbfr[], sysbfp; //System String Buffer and Position
|
||||||
|
|
||||||
/* System Subroutines */
|
/* System Subroutines */
|
||||||
void delchr(); //Delete previous character
|
void delchr(); //Delete previous character
|
||||||
@ -29,6 +30,7 @@ void newlin(); //Advance cursor to beginning of next line
|
|||||||
char polkey(); //Poll Console for character
|
char polkey(); //Poll Console for character
|
||||||
void prbyte(); //Print Accumulator as Hexadecimal number
|
void prbyte(); //Print Accumulator as Hexadecimal number
|
||||||
void prhex(); //Print Low Nybble of Accumulator as Hex Digit
|
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 putchr(); //Print ASCII character to Console
|
||||||
char putstr(); //Print ASCII string to Console
|
char putstr(); //Print ASCII string to Console
|
||||||
|
|
||||||
|
@ -16,44 +16,70 @@ char s[128]; //Test String
|
|||||||
|
|
||||||
char cval,cnum,ctot; //Character Function Variables
|
char cval,cnum,ctot; //Character Function Variables
|
||||||
int ivar,ival; //Integer 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 less, more; //Test Values for imin() and imax()
|
||||||
|
|
||||||
int yx, dd; //Function Arguments and Variables
|
int yx, dd; //Function Arguments and Variables
|
||||||
|
|
||||||
void cpival(icmp) {
|
void cpcval(cnum) {
|
||||||
if (>ival <> >icmp or <ival <> <icmp) {
|
if (cval <> cnum) {
|
||||||
putwrd(ival); puts("<>"); putwrd(icmp);
|
puthex(cval); puts("<>"); puthex(cnum);
|
||||||
failln();
|
failln();
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Test imin() and imax() */
|
void cpival(ichk) {
|
||||||
void minmax() {
|
if (>ival <> >ichk or <ival <> <ichk) {
|
||||||
|
prword(ival); puts("<>"); prword(ichk);
|
||||||
|
failln();
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Test imin() and imax() and icmp() */
|
||||||
|
void minmax(ctot) {
|
||||||
newlin();
|
newlin();
|
||||||
puts("LESS=$"); putwrd(less); puts(",MORE=$"); putwrd(more); newlin();
|
puts("IMIN(IACC($"); prword(less); puts("),$"); prword(more); puts(")=$");
|
||||||
puts(" IMIN()=$"); setsrc(less);
|
ival = imin(iacc(less),more); prword(ival); newlin();
|
||||||
ival = imin(more); putwrd(ival); newlin();
|
|
||||||
cpival(less);
|
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);
|
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() */
|
/* Test cvibcd() and upbcdi() */
|
||||||
void intbcd(ival) {
|
void intbcd(ival) {
|
||||||
newlin(); puts("CVIBCD($"); putwrd(ival); puts(")=$");
|
newlin(); puts("CVIBCD($"); prword(ival); puts(")=$");
|
||||||
cvibcd(ival); puthex(temp2); puthex(temp1); puthex(temp0);
|
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() */
|
/* Test itoa() and atoi() */
|
||||||
void itaati(ivar) {
|
void itaati(ivar) {
|
||||||
newlin();
|
//intbcd(ivar); newlin();
|
||||||
puts("ITOA($"); putwrd(ivar); puts(")=\"");
|
puts("ITOA(IACC($"); prword(ivar); puts(",S); ");
|
||||||
setdst(s); size = itoa(ivar); puts(s); putln("\"");
|
iacc(ivar); size = itoa(s); puts(" S=\""); puts(s); putln("\"");
|
||||||
puts("ATOI(\""); puts(s); puts("\")=$");
|
puts("ATOI(\""); puts(s); puts("\")=$");
|
||||||
ival = atoi(s); putwrd(ival); newlin();
|
ival = atoi(s); prword(ival); newlin();
|
||||||
cpival(ivar);
|
cpival(ivar);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,11 +88,11 @@ void itaati(ivar) {
|
|||||||
void addsub(ivar) {
|
void addsub(ivar) {
|
||||||
newlin();
|
newlin();
|
||||||
putint(ival); putc('+'); putint(ivar); putc('=');
|
putint(ival); putc('+'); putint(ivar); putc('=');
|
||||||
setsrc(ival); ctot, itot = iadd(ivar);
|
iacc(ival); ctot, itot = iadd(ivar);
|
||||||
putint(itot); puts(" carry=$"); puthex(ctot); newlin();
|
putint(itot); puts(", carry="); prhex(ctot); newlin();
|
||||||
putint(itot); putc('-'); putint(ivar); putc('=');
|
putint(itot); putc('-'); putint(ivar); putc('=');
|
||||||
setsrc(itot); ires = isub(ivar);
|
iacc(itot); ires = isub(ivar);
|
||||||
putint(itot); puts(" carry=$"); puthex(ctot); newlin();
|
putint(itot); puts(", carry="); prhex(ctot); newlin();
|
||||||
cpival(ires);
|
cpival(ires);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -74,15 +100,15 @@ void addsub(ivar) {
|
|||||||
void mltdiv(ivar) {
|
void mltdiv(ivar) {
|
||||||
newlin();
|
newlin();
|
||||||
putint(ival); putc('*'); putint(ivar); putc('=');
|
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();
|
if (cval) puts(" OVERFLOW!"); newlin();
|
||||||
putint(itot); putc('/'); putint(ivar); putc('=');
|
putint(itot); putc('/'); putint(ivar); putc('=');
|
||||||
setdst(itot); ires = idiv(ivar); putint(ires); newlin();
|
iacc(itot); ires = idiv(ivar); putint(ires); newlin();
|
||||||
cpival(ires);
|
cpival(ires);
|
||||||
ival>>; setsrc(ival); cval,itot = iadd(itot);
|
ival>>; iacc(ival); cval,itot = iadd(itot);
|
||||||
if (cval) return; //Number to Large to Modulo
|
if (cval) return; //Number to Large to Modulo
|
||||||
putint(itot); putc('%'); putint(ivar); putc('=');
|
putint(itot); putc('%'); putint(ivar); putc('=');
|
||||||
setdst(itot); ires = imod(ivar); putint(ires); newlin();
|
iacc(itot); ires = imod(ivar); putint(ires); newlin();
|
||||||
cpival(ires);
|
cpival(ires);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,50 +136,55 @@ void shftlr(cval, ivar) {
|
|||||||
cpival(itot);
|
cpival(itot);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
main:
|
main:
|
||||||
|
|
||||||
less = $009A; more = $00DE; minmax();
|
less = $009A; more = $00DE; minmax(1);
|
||||||
less = $789A; more = $78DE; minmax();
|
less = $789A; more = $78DE; minmax(1);
|
||||||
less = $7800; more = $BC00; minmax();
|
anykey();
|
||||||
less = $789A; more = $BCDE; minmax();
|
less = $7800; more = $BC00; minmax(1);
|
||||||
less = $F18F; more = $F18F; minmax();
|
less = $789A; more = $BCDE; minmax(1);
|
||||||
|
less = $F18F; more = $F18F; minmax(0);
|
||||||
anykey();
|
anykey();
|
||||||
|
|
||||||
itaati(&0);
|
doasc:
|
||||||
itaati(&234);
|
//itaati(&0);
|
||||||
itaati(&256);
|
itaati(&234);
|
||||||
itaati(&456);
|
itaati(&256);
|
||||||
itaati(&23456);
|
itaati(&456);
|
||||||
itaati(&$FFFF);
|
itaati(&23456);
|
||||||
anykey();
|
itaati(&$FFFF);
|
||||||
|
anykey();
|
||||||
|
|
||||||
ival = &23; addsub(&34);
|
doadd:
|
||||||
ival = &1234; addsub(&5678);
|
ival = &23; addsub(&34);
|
||||||
ival = &23456; addsub(&34567);
|
ival = &1234; addsub(&5678);
|
||||||
ival = &$7700; addsub(&$6600);
|
ival = &23456; addsub(&34567);
|
||||||
ival = &$7FFF; addsub(&$8000);
|
ival = &$7700; addsub(&$6600);
|
||||||
ival = &$FDEC; addsub(&$CDEF);
|
ival = &$7FFF; addsub(&$8000);
|
||||||
anykey();
|
ival = &$FDEC; addsub(&$CDEF);
|
||||||
|
anykey();
|
||||||
|
|
||||||
|
domlt:
|
||||||
|
ival = &23; mltdiv(&34);
|
||||||
|
ival = &123; mltdiv(&234);
|
||||||
|
ival = &255; mltdiv(&257);
|
||||||
|
anykey();
|
||||||
|
|
||||||
ival = &23; mltdiv(&34);
|
doshft:
|
||||||
ival = &123; mltdiv(&234);
|
shftlr(0,&$AA55);
|
||||||
ival = &255; mltdiv(&257);
|
shftlr(1,&$A55A);
|
||||||
anykey();
|
shftlr(2,&$F00F);
|
||||||
|
shftlr(3,&$0FF0);
|
||||||
shftlr(0,&$AA55);
|
shftlr(4,&$AA55);
|
||||||
shftlr(1,&$A55A);
|
shftlr(7,&$A55A);
|
||||||
shftlr(2,&$F00F);
|
anykey();
|
||||||
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);
|
|
||||||
|
|
||||||
|
shftlr(8,&$AA55);
|
||||||
|
shftlr(9,&$A55A);
|
||||||
|
shftlr(11,&$0FF0);
|
||||||
|
shftlr(12,&$AA55);
|
||||||
|
shftlr(15,&$A55A);
|
||||||
|
shftlr(16,&$F00F);
|
||||||
|
anykey();
|
||||||
|
|
||||||
goto exit;
|
goto exit;
|
||||||
|
Loading…
Reference in New Issue
Block a user