DIS16 v1.11 - PIC16C5X Disassembler ===================================== (c) 1998 Arsen Torbarina (Busy Bytes) ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ THIS IS YOUR PERSONAL REGISTERED VERSION OF 'DIS16', WITH YOUR NAME, ³ ³ ADDRESS AND A UNIQUE SERIAL NUMBER IMPRINTED ON IT. ³ ³ DO NOT DISTRIBUTE IT AND DO NOT MAKE ANY COPIES OF THIS PROGRAM ³ ³ THAT WOULD BE USED BY ANY OTHER PARTY. ³ ³ IT IS FOR YOUR PERSONAL USE ONLY ! ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ INCLUDED FILES The program includes the following files: DIS16.EXE - The program itself DIS16.TXT - Detailed program instructions (this text) CONVHEX.EXE - A freeware utility for converting 16-bit HEX files to 8-bit HEX files and vice versa DEMO.HEX - Demo HEX file READ.ME - Some important notes The executables are virus proofed! WHAT'S NEW DIS v1.01 (February 8, 1998) - added CONVHEX utility DIS v1.10 (February 19, 1998) - DIS16 directly supports 16-bit HEX format - much improoved tracing algorithm - much better unreachable blocks handling - added options for manual and auto setting the void-code - fixed some minor bugs DIS v1.11 (March 4, 1998) - fixed the bug which caused processor to be misinterpreted if code was loaded from BIN files PROGRAM DEFINITION DIS16 is an intelligent and easy-to-use disassembler for PIC16C5X microcontrollers. It produces a compact assembler source code from the binary data downloaded from a microcontroller's ROM and stored in a file. FEATURES * Supported processors: PIC16C54, PIC16C55, PIC16C56, PIC16C57, PIC16C58 Processor can be automatically detected from the code. * Supported file formats: - Intel 8-bit HEX Format (INHX8M, extension HEX) - Intel 16-bit HEX Format (INHX16, extension HEX) - Intel Split HEX Format (INHX8S, extensions HXL/HXH) - Raw binary file (BIN) * Symbolic names for special-purpose registers (F00-F07) and flags in the STATUS register (F03) that enhances program readability. * Intelligent program tracing that is used to: - Find and mark unreachable parts of a program - Detect multiple jumps (GOTO and CALL) - Tell apart program CODE from DATA tables - Determine required processor type, if none is specified - Detect and mark illegal instructions * Generating useful comments automatically Use of DIS16 disassembler requires an IBM PC/AT or compatible computer, running MS-DOS v4.1 or greater. RUNNING DIS16 DIS16 can be invoked through the command line as follows: DIS16 [options[+|-|argument]] filename Where filename is a name of a file that contains program code, and options are used to pass some additional instructions to the disassembler. The following file formats are supported by DIS16: - Intel 8-bit HEX Format (INHX8M, extension HEX) - Intel 16-bit HEX Format (INHX16, extension HEX) - Intel Split HEX Format (INHX8S, extensions HXL/HXH) - Raw binary file (BIN) NOTE: It is not necessary to write the filename extension, since the program determines the correct extension by itself. The program produces the following output files: filename.ASM Assembler listing, compatible with MPASM assembler; filename.LST Listing file suitable for printing and analyzing. Contains both HEX and symbolic code; filename.ERR Error file for details about the encountered errors and warnings NOTE: All the previously existing files with the same names will be overwritten without any notice or warning. OPTIONS Option Description [Default] --------------------------------------------------------------- /? or /h Display help /c[+|-] Set instructions case: +UPPER, -LOWER [UPPER] /p Specify processor type, where is: 16C[54|55|56|57|58] [Auto] /b=blsize Set minimum block size that will be presented using assembler's FILL statement [3] /d:addr1[-addr2][,addr3[-addr4]...] Force the code located between specified addresses to be interpreted as DATA (do not trace those addresses) E.g. /d:20-2F,1E0,1F0-1FF /v=HEXval Set void-code value (usually 0 or FFF) [Auto] /l[+|-] Enable or disable listing file [On] /e[+|-] Enable or disable error file [On] /q[+|-] Enable or disable quiet mode (suppresses screen output) [Off] ENHANCING THE PROGRAM READABLITY There are several mechanisms that DIS16 uses to enhance the program readability: Symbolic names Disassembler generates a table of used symbols, such as file-registers and STATUS register bits, and assigns them symbolic names as shown below: 1. Destination at "Byte-oriented file register operations": W EQU 0 ; Destination is W F EQU 1 ; Destination is f 2. File-register names INDF EQU 0x00 ; Indirect data addressing RTCC EQU 0x01 ; Real Time Clock/Counter PC EQU 0x02 ; Program Counter STATUS EQU 0x03 ; Status register FSR EQU 0x04 ; File Select Register PORTA EQU 0x05 ; Port A address PORTB EQU 0x06 ; Port B address PORTC EQU 0x07 ; Port C address [16C55,57] or F07 EQU 0x07 ; General purpose [16C54,56,58] F08 EQU 0x08 ; General purpose register ....... F1F EQU 0x1F ; General purpose register 3. STATUS register bit names C EQU 0 ; Carry bit DC EQU 1 ; Digit Carry bit Z EQU 2 ; Zero bit NOT_PD EQU 3 ; NOT Power Down bit NOT_TO EQU 4 ; NOT Time-Out bit PA0 EQU 5 ; Page-bit 0 PA1 EQU 6 ; Page-bit 1 PA2 EQU 7 ; Page-bit 2 (not used) Generating comments There are 3 groups of comments that can be generated automatically by DIS16: 1. Warnings: WARNING - Presumed value Next to 'PROCESSOR xxxxx' statement, where no processor type is given, so the processor type had to be automatically determined. It always gives the cheapest processor required. WARNING - PORTC not supported by this processor Occurs when 'TRIS PORTC' is encountered in the code for a 16C54, 16C56 or 16C58 processor. 2. Errors: ERROR - More than 12 bits Occurs if an instruction contains more than 12 bits, since PIC16C5X instructions have only 12 bits. ERROR - Illegal instruction Occurs if a code, *not* previously defined as DATA (see "Specifying DATA fields manually") does not correspond to any of the defined instructions. To prevent this error, all the addresses where it occurs define as DATA using the /d option. 3. Remarks: ; Addresses forced to be interpreted as DATA Below this, follows a list of the addresses that have been defined as DATA addresses. See also "Specifying DATA fields manually". ; Unreachable code The code below (to the first blank line) most probably will not be executed. However, it doesn't always have to be true, since DIS16 will not trace jumps made by modifying INDF and PC registers (e.g. 'MOVF PC'). See also "GOTO and CALL statements". ; End of unreachable code End of the unreachable code block. The code above this remark most probably will never be executed, and the code below is a part of the normal program flow. ; Could be .... List of credible jump destinations, written next to a GOTO or CALL instruction. Occurs only if there was multiple page addressing detected and there are more possible destinations (e.g. 'Could be L020 L220 L620'). See also "GOTO and CALL statements". Compacting blocks with FILL statement (/b option) If DIS16 encounters a byte that fills a block larger or equal to a given value, it will use a FILL statement to present it in the assembler code. That value is by default set to 3, but you can change it using the /b option (e.g. /b=10 will present all the blocks larger or equal to 10 bytes with a FILL statement). This value must be at least 2. Void-code blocks will *not* be presented by a FILL statement, and will be treatead as unused space. An ORG instruction will be used instead, to set address of the code that comes afterwards. If a byte that repeats is an instruction with no comma inside (e.g. 'SLEEP' or 'CLRW f'), then the following syntax will be used: FILL (instruction),repeats But if the instruction contains a comma (e.g. 'MOVF f,d'), then just its code will be written instead of the instruction itself, and the instruction will be written as comment, next to the FILL statement: FILL 0x330,0x4 ; RRF F10,F It had to be done that way, because the MPASM assembler wouldn't accept it otherwise. For example, let's take an assembler source like this one: ; --------- Original source code --------- processor 16c54 org 0x000 start rrf 0x10,1 rrf 0x10,1 rrf 0x10,1 rrf 0x10,1 ; Divide F10 by 16 movf 0x10,0 btfsc 0x03,2 ; Skip if ZERO goto notzero goto zero notzero incf 0x11,1 ; Increment F11 if not zero goto start org 0x100 zero incf 0x12,1 ; Increment F12 if zero movf 0x11,0 ; Copy F11 to W movwf 0x10 ; Copy W to F10 goto start ; and do it again. fill (clrf 11),0x1f0-$ ; Fill to 0x1ef with 'CLRF 1' end If you compiled it, and disassembled it again using DIS16, you would get the following output: ; ----------- Generated by DIS16 v1.11 Disassembler ----------- PROCESSOR 16C54 ; WARNING - Presumed value! W EQU 0 F EQU 1 Z EQU 2 STATUS EQU 0x03 F10 EQU 0x10 F11 EQU 0x11 F12 EQU 0x12 ORG 0x000 L000 FILL 0x330,0x4 ; RRF F10,F MOVF F10,W BTFSC STATUS,Z GOTO L008 GOTO L100 L008 INCF F11,F GOTO L000 ORG 0x100 L100 INCF F12,F MOVF F11,W MOVWF F10 GOTO L000 ; Unreachable code L104 FILL (CLRF F11),0xEC END TRACING THE PROGRAM There is an intelligent trace algorithm applied on the input code, that is used to: - Find and mark unreachable parts of a program - Determine possible destination pages in GOTO and CALL - Determine required processor type, if none is specified - Detect and mark illegal instructions - Determine which value is used for void-code (0 or 0xFFF) After loading, DIS16 starts to follow instruction by instruction of the loaded program, starting from the highest available address (for 16C57 it will be $7FF). Every time it encounters a "skip-if..." branch statement it branches and continues from the both possible addresses. Although the tracer follows all the jumps, it cannot get stuck into an endless loop, since each address can be visited only up to 5 times. When it encounters an address which has been executed more than that, the tracer closes that branch and returns to the point BEFORE it entered the branch. GOTO and CALL statements When a GOTO or CALL statement occurs, DIS16 disassembler will test which pages that instruction may point to. It is done by testing whether in the previous steps the Indirect Data Addressing register (INDF) or STATUS register (that contains page select bits) have been modified. If so, then it will be tested whether the possible destination addresses on all the available pages contain something other than a void-code. They will be considered as credible destinations for jump and thus written in the comment next to the GOTO or CALL instruction. NOTE: This algorithm is not 100% reliable, since there always could be some exceptions (e.g. if a GOTO deliberately points to a void-code statement), but in most cases it will give satisfying results. Furthermore, DIS16 will not consider jumps made by writing directly to PC (F02) or INDF (F00). For example, DIS16 could produce an output like this one: STATUS EQU 0x03 L000 ORG 0x000 .... ; (some code) MOVWF STATUS .... CALL 0x020 ; Could be L020 L220 CALL 0x030 ; Could be L030 L630 GOTO L000 .... L020 .... .... L030 .... .... ORG 0x220 L220 .... RETLW 0 ORG 0x630 L630 .... END You can see that in the CALL 0x020 instruction there are two addresses that are considered as destinations, since both of them point to a code other than a void-code. There is the same situation with the CALL 0x030 instruction. However, in the GOTO L000 statement there is only one possibility (and that is L000), since addresses 0x200, 0x400 and 0x600 contain void-code. Unreachable parts Any code that was never reached during the tracing procedure will be marked with an "Unreachable code" remark. However, it doesn't always mean that the code cannot be reached (see the NOTE in the previous paragraph). Specifying DATA fields manually Since the tracer treats all the code by default as executable instructions, sometimes you will have to tell to the disassembler which addresses are to be treated as DATA and not to be traced. For example, if you take the following file (test.hex): :08000000000A44004100540015 :020008004100B5 :00000001FF and you try to disassemble it by typing only: DIS16 test.bin you will get the following output: ORG 0x000 L000 GOTO L000 ; Unreachable code L001 DW 0x044 ; ERROR - Illegal instruction DW 0x041 ; ERROR - Illegal instruction DW 0x054 ; ERROR - Illegal instruction DW 0x041 ; ERROR - Illegal instruction END But if you tell the disassembler that the code between addresses $001 and $004 is DATA section by typing: DIS16 test.hex /d:1-4 the following output is produced: ; Addresses forced to be interpreted as DATA: ; 0x001 - 0x004 ORG 0x000 L000 GOTO L000 DW 0x044 ; 'D' DW 0x041 ; 'A' DW 0x054 ; 'T' DW 0x041 ; 'A' END You can also specify up to 100 different DATA areas, such as in: DIS16 prog.hex /d:100-1FF,210,250-25F See also "Compacting blocks with FILL statement". NOTE: Data blocks will never be marked with the "Unreachable code" comment. Determining processor type Although advisable, it is not always necessary to specify the processor type, since DIS16 can determine by itself the cheapest processor required for the given program. The choice is made regarding the program length and the used ports. For example, if it encounters a TRIS 7 (initialize Port C) instruction, it is obvious that it requires a 16C55 or 16C57 processor. Besides, if the program contains up to 1K, the suggested processor will be 16C55. Illegal instructions Any encountered illegal instruction (e.g. $001, $041-$04F) that was not previously defined as DATA (see the "Specifying DATA fields manually" chapter) will be presented using a DW statement. Also there will be an "ERROR - Illegal instruction" comment added next to the DW statement and to the ERR file. CONVHEX UTILITY CONVHEX is an additional utility that converts the Intel 8-bit INHX8M format to Intel 16-bit INHX16 format and vice versa. It will automatically recognize the required format. For example: CONVHEX old.hex new.hex DIS16 new.hex