Index | wersja polska |
The PB-2000C supposedly doesn't permit to execute arbitrary machine code, but can be tricked into it by changing the address of the [BRK] key handle routine using the built-in monitor.
When the [BRK] key is pressed, an indirect jump is taken to the address contained in the ACJMP system variable &H0CE2, but only in bank 0 (ROM), while the user code can be placed only in bank 1 (RAM). The change of the PC memory bank proved to be possible by pointing the ACJMP vector to the following piece of code in the microprocessor's internal ROM:
0276: PPS $6 0277: PST UA,$6 0278: RTN
By a fortunate coincidence of circumstances it leads to address &HC021 in bank 1 (the UA register contains &H11). It is safe to change the PC memory bank, because the interrupts are disabled at this point (the IE register contains &H00).
A PB-2000C with 64kB RAM is required.
Select the menu item [memory] and resize the memory block allocated for the files to 16350 bytes. Now the first file will start from address &HC021. It provides a safe place for the machine code.
<memory> c file work 58879 41505 16350 1024 free 16350 1024 c,file?41505,16350 |
The first directory entry reserved for the file that stores the machine code will be modified by the loader described below. Ensure that it doesn't contain any valuable data, since it will be overwritten.
The program displays the text "Hello World!" and waits for pressing any key before returning to the system. The source should be assembled with the HD61 assembler with the option /p to produce a PBF-type output file.
ORG &HC021 START &HC021 PST UA,&H55 LDW $2,&H2AF0 ;restore the default jump address LDW $23,&H3280 ;BRSTR, set ACJMP CAL SYSCAL LDW $23,&H328F ;select the LCD as the output device CAL SYSCAL LDW $15,M1 ;pointer to the string LD $17,M2-M1 ;length of the string LDW $23,&H293B ;display string CAL SYSCAL LDW $23,&H5774 ;KYIN, wait for a pressed key CAL SYSCAL PST UA,&H54 JP &H707C ;return to the system, mode CAL ; call to a routine in bank 0 pointed to by $23,$24 SYSCAL: GST UA,$6 PHS $6 LDW $6,&H0276-1 PHSW $7 PST UA,&H54 JP $23 M1: DB &H0C,"Hello World!",&H0D,&H0A M2:
The program loads machine code in the PBF format from the PB-2000C ramdisk, or from the floppy disk or from the RS232 interface, converts it to binary and stores in the first ramdisk file. The previous file in the first directory entry will be overwritten.
main() { FILE *infp,*outfp; char filename[24]; char byte[2]; unsigned addr1,addr2,x,sum; /* sanity check */ if (*(short*)0x0AAA != 0xC021) { printf ("Bad system configuration\n"); abort(); } /* open the PBF file */ for (x=0;x<24;x++) filename[x]='\0'; printf ("PBF file name: "); scanf ("%23s",filename); if ((infp=fopen(filename,"rt")) == NULL) { printf ("Input file open error\n"); abort(); } /* change the name and type of the first file in the directory (if exists) */ addr2 = *(unsigned short*)0x0AB4; if (*(unsigned short*)0x0AB0 < addr2) { for (addr1=addr2-27; addr1<addr2-15; addr1++) *(char*)addr1 = '$'; } if ((outfp=fopen("$$$$$$$$.$$$","wb")) == NULL) { printf ("Output file open error\n"); abort(); } /* read the input file header */ for (x=0;x<13;x++) { if ((filename[x]=fgetc(infp)) == ',') break; } filename[x]='\0'; if (x>12 || fscanf(infp,"%u,%u,%u\n",&addr1,&addr2,&x) != 3) { printf ("Bad header\n"); abort(); } if (addr1 != 0xC021) { printf ("Bad ORG\n"); abort(); } /* PBF->BIN conversion */ sum=0; while (addr1<=addr2 && feof(infp)==0) { if ((byte[0]=fgetc(infp)) != ',') { byte[1]=fgetc(infp); sscanf(byte,"%2X",&x); if (fputc(x,outfp) != x) { printf ("File write error\n"); abort(); } sum+=x; addr1++; } else { if (fscanf(infp,"%u\n",&x) != 1 || x != sum) { printf ("Bad checksum\n"); abort(); } sum=0; } } fclose(outfp); fclose(infp); if (addr1<=addr2) { printf ("Unexpected EOF\n"); abort(); } if (rename("$$$$$$$$.$$$",filename)) { printf ("Rename failed\n"); abort(); } printf ("Done!\n"); }
Type CLEAR MON in the CALC mode to enter the monitor.
Write value &H0276 to the ACJMP system variable at address &H0CE2.
>E0CE2 0CE2 AE-76 6F-02 FF- |
Press the [BRK] key.
Hello World! _ |