Here is a very short msdos program to generate the first 9304 digits of pi. This program has only 125 bytes. In uuencoded form: begin 644 tinypi.com MN31_N-`'_+]]`?.KNS1_4S/`F5.+\O?CEE+WXUH#PI>X$"?1XU/WIWL!`\83 MUTLS_Y>2]_.7B_(STO?SEI+W\UN)EWL!,](#QA/76TMUQ%!2]S8A`5(#P;D$ C`#/2]S9[`5+B][D$`%JT`H#",,TAXO996EA;@^L.=97#"@`` ` end rob duijs rbdu@pi.net ==================================================== the following is the disassembly by Greg Smith ==================================================== PI.COM for DOS: print out 9304 digits of PI. The length of the program is 125 bytes. I don't know who wrote it. This is a disassembly of PI.COM, with labels and comments added. I haven't attempted to explain how it works; however the analysis is enough to prove that it will run to completion and doesn't contain a virus or anything nasty (but see the note below about memory). For you young-uns, the rules for .COM files are as follows. (this was intended as a CP/M compatibility mode) - Program loads at CS:100. PSP is at CS:0 (don't worry if you don't know what a PSP is). - SS, ES and DS initially set to CS value. Segments are ignored if you don't want to use more than 64K. - SP set to FFFE initially (room permitting) - SP defines initial upper memory limit. - RET from initial SP is OK to exit program. This program uses almost all of the 64K normally available to a COM file, and does not check to see if it is available first. If it is run in a situation where it doesn't get a full 64K (very rare) it will probably crash the system. If its STACK overruns its Buffer ( for instance, because of interrupt routines pushing stuff on the stack, again very unlikely) it may produce incorrect results, but will still produce the correct number of digits and exit cleanly. Greg Smith, Toronto, Canada. gsmith@passport.ca ; ; ; The program uses a memory buffer at 017Dh, of length 32564 words. ; ; The first operation is to clear that to 2000 0100 B9347F MOV CX,32564 ; Buffer Len 0103 B8D007 MOV AX,2000 ; Fill value 0106 FC CLD 0107 BF7D01 MOV DI,Buffer 010A F3AB REPZ STOSW ; CX is zero now. This will be used later. ; ; The rest of the program is an outer loop, and an inner ; loop. BX is the loop control variable. In the outer loop, BX ; goes down by 14: 32564,32550,32536,... 14. Don't ask me why. ; Total of 2326 loops; Each loop prints 4 digits, for ; a total of 9304 digits. ; ; BX is pushed at the start of the outer loop and popped just ; before the end. ; The inner loop runs with BX decrementing from 'i' down to 1, ; where 'i' is the index (BX value) of the outer loop. This inner ; loop index is likewise protected on the stack. Call it 'j'. ; ; incidentally, MUL BX means 'multiply (unsigned) AX by BX and ; place the high part of the result in DX and the low part in AX'. ; 010C BB347F MOV BX,32654 010F 53 Loop1: PUSH BX ; save loop index 0110 33C0 XOR AX,AX 0112 99 CWD ; DX=AX=0 now ; ; 0113 53 Loop2: PUSH BX ; save index 0114 8BF2 MOV SI,DX 0116 F7E3 MUL BX 0118 96 XCHG SI,AX 0119 52 PUSH DX 011A F7E3 MUL BX 011C 5A POP DX 011D 03C2 ADD AX,DX 011F 97 XCHG DI,AX ; ; Now DI:SI contains the 32-bit product of BX and whatever was in DX:AX ; at the start of the loop. We are going to multiply Buffer[j-1] ; by 10000 below, giving a result in DX:AX; to that the product in ; DI:SI will be added. ; 0120 B81027 Lab10K: MOV AX,10000 0123 D1E3 SHL BX,1 ; find j*2 = byte index 0125 53 PUSH BX ; save byte index for below. 0126 F7A77B01 MUL WORD PTR [BX+Buffer-2] 012A 03C6 ADD AX,SI 012C 13D7 ADC DX,DI ; ; 012E 4B DEC BX 012F 33FF XOR DI,DI 0131 97 XCHG DI,AX 0132 92 XCHG DX,AX ; ; OK, now BX = 2*j-1, and DX=0, AX = the high part of the 32-bit sum ; from above. The low part is in DI. ; The 'DIV BX' instruction divides DX:AX by BX, leaving the ; quotient in AX and the remainder in DX. ; ; The next sequence divides the 32-bit value in AX:DI by ; 2*j-1, saving the remainder in Buffer[j-1] ; 0133 F7F3 DIV BX 0135 97 XCHG DI,AX 0136 8BF2 MOV SI,DX 0138 33D2 XOR DX,DX 013A F7F3 DIV BX 013C 96 XCHG SI,AX 013D 92 XCHG DX,AX 013E F7F3 DIV BX ; ; 0140 5B POP BX ; get 2*j back -array index 0141 89977B01 MOV [BX+Buffer-2],DX ; store result ; ; The quotient's upper part is in DI now; the lower part is ; the sum of AX and SI (and there is a carry to take care of..) ; This quotient is found, and placed in DX:AX for the next ; iteration of the inner loop. ; 0145 33D2 XOR DX,DX 0147 03C6 ADD AX,SI 0149 13D7 ADC DX,DI ; ; Get inner loop count off stack, decrement it, loop if not zero. ; 014B 5B POP BX 014C 4B DEC BX 014D 75C4 JNZ Loop2 ; ; OK, nothing on the stack now except for the outer loop count. ; Save AX:DX, then divide them by 10000. Note: The first time ; we hit this, CX contains 0 from the initial fill operation. ; Later, it contains something from the previous outer loop: : the DX (remainder) from the first DIV below is pushed, ; and popped into CX further down. ; The quotient from the DIV below is added to the CX (remainder ; from the previous pass). ; There is a little loop below which breaks the up this AX ; value into four digits, pushing each on the stack, and ; then another loop which pops them, converts to ASCII, and prints ; them. The push/pop causes the digits to come out in the right order. ; ; 014F 50 PUSH AX ; Save DX:AX 0150 52 PUSH DX 0151 F7362101 DIV WORD PTR [Lab10K+1] ; pull 10K out of above 0155 52 PUSH DX ; Save remainder for next 0156 03C1 ADD AX,CX 0158 B90400 MOV CX,4 015B 33D2 PshLoop: XOR DX,DX 015D F7367B01 DIV WORD PTR [Ten] 0161 52 PUSH DX 0162 E2F7 LOOP PshLoop 0164 B90400 MOV CX,4 0167 5A PopLoop: POP DX 0168 B402 MOV AH,2 ; Print Char DOS call 016A 80C230 ADD DL,'0' ; c 016D CD21 INT 021h ; DOS call 016F E2F6 LOOP PopLoop ; ; now pop the remainder for the next loop, and restore DX:AX ; 0171 59 POP CX 0172 5A POP DX 0173 58 POP AX ; ; Get outer loop count off stack, subtract fourteen, jump if not zero. ; 0174 5B POP BX 0175 83EB0E SUB BX,14 0178 7595 JNZ Loop1 ; ; All done! 017A C3 RET 017B 0A00 Ten: DW 10 017D Buffer label word ; The next 32654 words are used as a working area, but are ; not part of the .COM file. ; ; That's it! ;------------------