; I may add more comments to this file in the future... ; An annotated Assembly Listing of FIRE.COM ; ========================================== ; ( The purpose of most lines is NOT yet noted. This is just to give you ; a general idea of the flow of the program AND to point out the ; instructions which the old 8086-based MS-DEBUG can NOT understand!) ; Note: Program assumes DOS will zero the AH register when run! 0100 MOV AL,13 ; INT 10h Function 00h; AL=13h is Video Mode: INT 10 ; Graphics Mode = 320x200 at 256 colors ; (Pixels=8x8 and Addresses begin at: A000h.) ;========================================================================== ; See Ralf Brown's INTERRUPT LIST for a comprehensive listing of ALL the ; functions and parameters for any INT you might possibly want to examine! ;========================================================================== ;=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+= ; ; NOTE: In the code listings below, I've added some comments ; using the variables which The Bitripper assigned in ; his own listing. Here are their values and/or memory ; locations: ; ; FlH = 100 ; 64h = 100 ; FlW = 320 ; 140h = 320 ; [The Height and Width in pixels for FIRE.COM's screen mode.] ; ; Spots = 200 ; C8h = 200 ; ; Recall that the length of our code is 1ABh bytes. ; ; RandSeed = [1ACh through 1AFh] a Double-Word directly ; following the end of the code section. ; ; Flames = [ 1B0h through 7EAFh] or 7D00h bytes long. ; (flw*flh) = 320*100 = 7D00h = 32,000 bytes. ; ; New_Flames = [7EB0h through FBAFh] another 7D00h bytes. ; 0000h thru FBAFh = 64,432 bytes. ; Thus, most of the segment in memory is used! ; ( 1 segment = 0000h thru FFFFh = 64kb = 65,536 bytes.) ;=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+= XOR AX,AX ; Reset AX to zero MOV DI,01B0 ; mov di,offset flames MOV CX,7D00 ; 7D00h = 32,000 (Counter Register) REPZ ; These two instructions Store Words STOSW ; (or _fill_) the memory beginning at ; DI (Destination Index) 7D00h times. ; Since these are WORDS, 64,000 bytes ; of memory will be filled with 00h ; (the value in AX) beginning at 1B0h ; and ending with FBAFh. ; AX=00h from previous XOR instruction. MOV DX,03C8 ; | OUT DX,AL ; Output (or write) 00h on port 3C8h. ; (Note: An OUT instruction is often thought of as a WRITE, and an IN instruction as a READ.) ;========================================================================== ; From Ralf Brown's PORTS.LST file: ; ; "03C8 RW (VGA,MCGA) PEL address register (write mode) ; Sets DAC in write mode and assign start of color register ; index (0..255) for following write accesses to 3C9h. ; Don't read from 3C9h while in write mode. Next access to ; 03C8h will stop pending mode immediatly." ;========================================================================== INC DX ; DX=3C9h DEC CL ; This turns the 00h in CX into FFh ; (256) for the 256 RGB colors. Check_Red: 0115 CMP BL,3C ; [3Ch = 60] JNB 011F ; same as: jae (to: Check_Green) ADD BL,04 JMP 0127 ; SHORT Non-conditional jump to: ; "Check_Number" Check_Green: 011F CMP BH,3C ; [3Ch = 60] JNB 0127 ; same as: jae (to: Check_Number) ADD BH,04 Check_Number: 0127 MOV AL,BL OUT DX,AL ;========================================================================== ; Again, from Ralf Brown's PORTS.LST file: ; ; "03C9 RW (VGA,MCGA) PEL data register ; Three consequtive reads (in read mode) or writes (in write ; mode) in the order: red, green, blue. The internal DAC index ; is incremented each 3rd access. ; bit7-6: HiColor VGA DACs only: color-value bit7-6 ; bit5-0: color-value bit5-0" ;========================================================================== MOV AL,BH OUT DX,AL XOR AL,AL ; Reset AL to zero. OUT DX,AL ; Output (or write) 00h on port xxx h. LOOP 0115 ; Loop to Check_Red Do_Fire: 0132 MOV CL,C8 ; C8h = "spots" = 200 Put_Spots: 0134 ADD WORD PTR [01AC],62E9 ; [01AC] = randseed ADD BYTE PTR [01AC],62 ; 62h = 98 = flh-2 ADC WORD PTR [01AE],3619 ; [01AE] = randseed+2 MOV AX,[01AE] XOR DX,DX ; Reset DX to zero. MOV BX,0140 ; 140h = "flw" = 320 DIV BX MOV SI,DX DEC BYTE PTR [SI+7D70] ; [si + flames + ((flh-1)*flw) ] ; [SI + flames + ((100-1)*320) ] ; [SI + flames + 31,680 ] ; [SI + flames + 7BC0h ] ; [SI + 01B0h + 7BC0h ] ; [SI + 7D70h ] LOOP 0134 ; Loop to: "Put_Spots" MOV SI,02F1 ; 02F1h = flames + 1 + flw MOV DI,7EB1 ; 7EB1h = new_flames + 1 MOV CL,62 ; 62h = 98 = flh - 2 Avg_Col: 015F MOV DX,013E ; 13Eh = 318 = flw - 2 Avg_Row: 0162 MOV BL,[SI+FEC0] ; Or: MOV BL,[SI-0140] hint! ; same as: BL,[SI-flw] MOV AL,[SI-01] ADD BX,AX MOV AL,[SI+01] ADD BX,AX MOV AL,[SI+0140] ; same as: AL,[SI+flw] ADD BX,AX ; DB C1 ; The old 8086-based DEBUG doesn't ; understand this instruction(!) ; Anytime you see a "DB" in the code you should become suspicious ; of the Disassemblers ability to understand newer instructions. ; JMP 017B ; This code (bytes EB02) is actually part ; of the instruction above which DEBUG ; didn't know was a three-byte instruction. ; On a newer Assembler and Disassembler this instruction would be ; CORRECTLY interpreted as: SHR BX,2 ; Shift contents of BX by 2 bits right ; This essentially performs a divide by ; Four (/4) operation. MOV [DI],BL INC SI INC DI DEC DX JNZ 0162 ; Jump if not zero to: Avg_Row INC SI INC SI INC DI INC DI LOOP 015F ; Loop to: Avg_Col MOV SI,7EB2 ; 7EB2h = new_flames + 2 MOV DI,01B2 ; 1B2h = flames + 2 MOV CX,3E7E ; 3E7Eh = 15,998 = flw * flh/2 - 2 PUSH CX PUSH DI REPZ ; On more modern Assemblers, these MOVSW ; two instructions are usually shown ; together on one line as: repe movsw POP SI ;------------------------------------------------------------------------- ; DB 68 ; Once again, the old 8086-based DEBUG ; ; doesn't understand this instruction ; ; either! It's the beginning of an ; ; immediate WORD value PUSH instruction ; ; which includes the next two bytes... ; ; and really messes things up a bit! ; ; ADD [BX+SI+BF07],AH ; NOT THIS AT ALL! (Bytes: 00A007BF) ; ADD BH,[DI+59] ; NOR THIS! (Bytes: 027D59 ) ;------------------------------------------------------------------------- ; The CORRECT SEQUENCE OF INSTRUCTIONS IS ACTUALLY: PUSH A000 ; Push WORD A000h onto Stack. (6800A0) POP ES ; So ES now contains A000h. (07) MOV DI,7D02 ; (Bytes: BF027D) ; 7D02h = (200-flh)*320+((320-flw)/2)+2 ; Why use formula? Always = 32,002 POP CX ; (Byte: 59) REPZ MOVSW ; Or: repe movsw PUSH DS ; Move DS into POP ES ; --> ES MOV AH,01 ; INT 16h, Function 01h: INT 16 ; Read Keyboard Status ; Check BUFFER, but don't CLEAR it. ; Return: ZF clear if character in buffer ; AH = scan code, AL = character ; ZF is SET if no character in buffer. JZ 0132 ; Jump if zero to: Do_Fire ; Program continues endlessly until ; user presses a key... Any key! Key_Pressed: MOV AX,0003 ; Function=00h (AH register!) Set VIDEO INT 10 ; mode to (AL=03h) Resets it to normal ; 80 columns x 25 lines; color available. 01AB RET ; The code has the structure of a subroutine ; which could be called from another program. [ Lastest Revision: 14 OCT 2000 ]