/******************************************************************************/ /* SERNO3.C Version 1 Revision 00 2 January 1985 */ /******************************************************************************/ /******************************************************************************/ /* cpm_ser_num */ /* Copyright (c) 1985 by Paul M. Sittler */ /* No rights reserved, or all rights reversed. . . */ /******************************************************************************/ cpm_ser_num() { /******************************************************************************/ /* SERNO3.C was inspired by SERNO2.ASM by Charles Horn, dtd 31 January 1984. */ /* I coded it into 'c' so that I could add this function to some of my */ /* programs. While I was at it, I thought I would write it up as a tutorial */ /* and show how 'c' could do most anything that could be done in assembler. */ /* The finished program, of course, is somewhat larger and a trifle slower */ /* than SERNO2.COM, but it took me a LOT less time to code it in 'c' than it */ /* would have taken me in assembler. Enjoy, . . . */ /* */ /* Notes and tutorial on the CP/M serial number: */ /* */ /* The CP/M serial number is located at the beginning of the BDOS Page */ /* of memory. This is exactly six bytes ahead of the BDOS entry address */ /* that is accessed by the BDOS jump at 0005H. It usually consists of */ /* three decimal numbers of the form nnn-nnnn-nn, or num1-num2-num3. Num1 */ /* and num3 are one-byte numbers, and num2 is a two byte number. As an */ /* example, a serial number of (decimal) 123-4567-8, */ /* would be coded as (hexadecimal) 7B-11D7-08. */ /* */ /* At the actual BDOS Page location, the numbers would appear as: */ /* */ /* At (BDOS ENTRY - 6) >>>>----> 7B 08 00 00 11 D7 */ /* || || || || || || */ /* Serial Number num1 ---------++ || || || || || */ /* Serial Number num3 -------------++ || || || || */ /* Zero filled bytes -----------------++--++ || || */ /* Serial Number num2 -------------------------++--++ */ /* */ /* The same number string is coded into MOVCPM.COM, starting at address */ /* (usually) 1200H. When MOVCPM runs, it checks to see that these two numbers*/ /* match. If they do NOT match, MOVCPM reports "SYNCHRONIZATION ERROR" and */ /* quits. This will prevent one from generating a system image in memory */ /* for customization. */ /* */ /* This program reads the BDOS entry address from the BDOS jump at 005H, */ /* sets a pointer to the beginning of the serial number, reads the serial */ /* number into memory, and prints them out. */ /* */ /******************************************************************************/ /******************************************************************************/ /* local variables */ /******************************************************************************/ int Bdos, /* address in memory of the BDOS entry */ sernum_addr; /* address in memory of the serial number */ unsigned serno2; /* unsigned so it can be bigger than +/- 32760 */ char *ptr, /* all purpose pointer */ serno1, /* serno1 and two are only one byte numbers */ serno3; /* so declare them as character */ /******************************************************************************/ /* code starts here */ /******************************************************************************/ ptr = 6; /*set pointer to BDOS entry address */ Bdos = (*ptr++) + (*ptr++ << 8); /* Bdos entry address */ sernum_address = Bdos - 6; /* Back up six bytes */ ptr = sernum_address; /* point to serial number address */ serno1 = (*ptr++); /* store value at pointer into serno1 */ serno3 = (*ptr++); ptr += 2; /* skip those zeros */ serno2 = (*ptr++ << 8) + (*ptr); /* Most significant bit first, */ /* Least significant bit second. */ printf("\n\tOperating system serial number is at location %04x.", sernum_address); printf("\n\tserial number is %02x-%04x-%02x hex,", serno1,serno2,serno3); printf("\n\t or %d-%u-%03d decimal.\n", serno1,serno2,serno3); }