D52 Disassembler User's Manual

8052 Disassembler for Linux and Windows
GNU General Public License Version 3
Copyright 2007 by Jeffery L. Post
j_post <AT> pacbell <DOT> net
Hosted on www.8052.com
Version 3.4.1 - September, 2007

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
The file COPYING contains the full text of the GNU General Public License, Version 3.
NOTE: As Novell and Microsoft are in violation of the GPL, this software may not be distributed by either Novell or Microsoft. The same prohibition applies to any company that enters into an agreement with Microsoft regarding Microsoft's phony patent claims against Linux. In addition, no one who cannot or will not honor ALL the requirements of GPL version 3 may distribute this software.

### TABLE OF CONTENTS

- Introduction
- Disclaimer
- Getting Started
- Command Line Options
  A option - define ascii macro
  B option - disassemble binary file
  D option - put data in comment field
  H option - disassemble hex file
  I option - add include for 'sfr52.inc' file
  K option - disassemble for older (DOS) Keil A51
  N option - output operands in C style format (0xcd instead of 0cdh)
  P option - put dot '.' in front of pseudo ops (eg: .equ instead of equ)
  S option - change pseudo op for ascii strings
  T option - trace and analyze code before disassembly
  U option - output labels, mnemonics, etc in upper case
  X option - add hex offset to addresses
  Z option - read cycle count file (d52 only)
- Control File Directives - define interpretation of disassembly data
  A directive - address data
  B directive - byte (8 bit) data
  C directive - code (force disassembly)
  D directive - data type (label or symbol)
  F directive - define SFR label
  I directive - ignore data (do not disassemble)
  K directive - define name for SFR bit
  L directive - define label
  M directive - define name for bit addressable memory
  N directive - suppress label generation for an address
  O directive - add hex offset to addresses
  P directive - patch inline code
  R directive - define register name
  S directive - define symbol
  T directive - ascii text
  W directive - word (16 bit) data
  X directive - define name for specific operand
  Y directive - define name for specific operand but suppress EQU generation
  Z directive - specify code for which to generate cycle counts
  # directive - header comment
  ! directive - inline comment
- A Note on Symbols, Labels and Names
- Format of Output File
- Summary
- 8052 Register Maps
- 8052 Bit Addressable SFRs
- 8052 Bit Addressable Memory

Back to top

#### Introduction

The D52 disassembler allows the user to specify memory areas as code, binary data (8 or 16 bit), ascii text, address tables, or data that should be ignored (not disassembled). You may specify such areas in an ascii text file with the same name as the file to be disassembled, but with an extension of ctl (for example: program.ctl controls the disassembly of program.hex or program.bin).
With the use of a control file, you can, by an iterative process, get a progressively more meaningful disassembly by modifying the control file based on examination of the output of previous runs of the disassembler. You can also specify names for labels and symbols in the control file, resulting in a much more readable source file.
Labels and symbols may have as many characters as will fit in one line of the control file, but some cross assemblers (and especially cross linkers) will truncate any more than some fixed number of characters. Consult your cross development tool documentation. Labels and symbols are not case sensitive.
The control file may exist in either the current directory or the directory of the file to be disassembled. If it is in both directories, the control file in the current directory will take precedence. The output file will always be placed in the current directory.
The getting started section of this document gives some minimal information for users who are eager to try out the disassembler. For best use of the disassembler, however, you should read the sections on command line options and control file directives before proceeding.
Much of the information in this manual also applies to the 8048 and Z80 disassemblers. Invoking the disassemblers without any command line parameters will display a list of options.
Disclaimer

D52 is a tool for educational use and for recovering source code that has been lost or is unavailable. Disassembling a program may be unethical or illegal under some circumstances. It is your sole responsibility to determine whether use of D52 for a particular purpose is both legal and ethical.
Back to top

#### Getting Started

D52 is a command line disassembler. To disassemble a file called 'program.bin' or 'program.hex', type in (at the command line prompt):

|  |  |  | d52 -d program

A control file with the same name as the file to be disassembled, but with an extension of '.ctl' can be created in which you can specify areas of memory to be ascii text, 8-bit binary data, 16-bit binary data, etc. A control file is not necessary for disassembly, but as will be seen, it will provide for a much more complete disassembly. The t option will cause D52 to trace and analyze the code before disassembly, and will create a preliminary control file.
If a file extension is not provided and neither the b option nor the h option is specified on the command line, the disassembler will first search for a hex file and, if it is not found, will then search for a bin file. The disassembler can be forced to look for only one or the other by specifying either the binary or the hex option on the command line:

|  |  |  | d52 -db program |  |  |  |  | for the file program.bin, or
|  |  |  | d52 -dh program |  |  |  |  | for the file program.hex

If a file extension of '.hex' or '.bin' is provided in the filename (ie: d52 test.hex), that is equivalent to using the h option or b option.
D52 will produce a file named 'program.d52' containing the disassembly of the 8051/8052 instructions in the original hex or binary file. It is very useful on the first few disassemblies to use the d option , which adds a comment field to every line. The comment field contains the hexadecimal address of each instruction, the hex data for each byte in the instruction, and the ascii code for each byte of the instruction.
Example:

|  |  |  |  | (opcode/operands) | (address) | (data) | (ascii)
|  |  |  |  | orl a,#42h | ; 0df6 | 44 42 | DB

This makes it easy to spot areas of ascii text or other nonexecutable code, and you can then modify the control file to tell the disassembler that these areas should be treated as some other kind of data on subsequent disassemblies. Please see the section on control file directives for specific information.
By examining the output file and then modifying the control file based on the information obtained, you can get a progressively better disassembly of your program. Generally, about half a dozen iterations of the disassembly are enough to produce a very readable source file that can then be modified and reassembled.
Back to top

#### Command Line Options

Command line options modify the operation of the disassembler. They may be specified on the command line using either Unix style options:

|  |  |  |  | d52 -db filename

or DOS style options:

|  |  |  |  | d52 /d /b filename

Options may be entered in a freeform fashion (in any order or format) provided that any options preceeding the filename of the program to be disassembled must begin with either a dash (-) or a slash (/). For example:

|  |  |  |  | d52 /db filename -x1000
|  |  |  |  | d52 filename -d b x1000
|  |  |  |  | d52 -d filename bx1000

all mean exactly the same thing and will cause the disassembler to behave in exactly the same way. Exceptions are that the X option , if used, must be the last option given, and if both the A option and the S option are used, the S option must preceed the A option.
Note that the file name specified on the command line does not include the .hex or .bin extention.
Command line options are:

#### A Option (ascii macro)

The A option tells the disassembler to change the db/defb pseudo op to the ascii macro (pseudo op 'ascii' instead of 'db' or 'defb') for areas defined as ascii text. This will cause the disassembler to include a macro definition in the disassembly output file that should expand to 'db' for the cross assembler. To use this option, your cross assembler must be able to handle macros, and in particular, D52's macro format. If used in conjunction with the S option , the S option must come first on the command line.
There are some caveats regarding the ascii macro. The intent of this macro is to make ascii text easier to find in the output file. Once you're satisfied with the readability of the output file, you may want to run the disassembler once more without the A option to produce a file compatible with your cross assembler.
Some cross assemblers treat certain characters within a macro as special meta-characters. The Huntsville Microsystems HMA8051, for example, regards the characters '#', '.' and '\' as special within a macro. If these characters occur in ascii text using the ascii macro of D52, the assembler will do strange and not so wonderful things with them. If this happens, just do not use the A option (by default, it is off).
A problem that will be common with all cross assemblers is that the disassembler does not currently treat the single quote (') character differently than it does other characters within ascii text. Since the disassembler delineates ascii text (whether using the A option or not) with the single quote character, its presence in ascii text areas will cause problems. The only solution to this is to manually edit the output file of the disassembler or to define the byte of the single quote as a binary byte in the control file (see the B control file directive ).

#### B Option (read binary file)

The B option forces the disassembler to read a binary file (extention '.bin') instead of an Intel hex file (extention .hex). If neither the B option nor the H option are specified, the disassembler will first search for a file with an extention of .hex, and if not found, will then search for a binary file with an extention of .bin.

#### D Option (put data in comment field)

The D option tells the disassembler to include a comment field in each disassembled line. The comment field will contain the hexadecimal address of each instruction, the hex data for each byte in the instruction, and the ascii code for each byte of the instruction. Example:

|  |  |  |  | (opcode/operands) | (address) | (data) | (ascii)
|  |  |  |  | orl a,#42h | ; 0df6 | 44 42 | DB

This makes it easy to spot areas of ascii text or other nonexecutable code, and then modify the control file to tell the disassembler that these areas should be treated as some other kind of data on subsequent disassemblies. Please see the section on control file directives for specific information.

#### H Option (read hexadecimal file)

The H option forces the disassembler to read an Intel hex file (extention '.hex') instead of a binary file (extention '.bin'). If neither the B option nor the H option are specified, the disassembler will first search for a file with an extention of '.hex', and if not found, will then search for a binary file with an extention of '.bin'.

#### I option (add include for 'sfr52.inc' file)

The I option adds this line to the .d52 disassembly file:

    	include	"sfr52.inc"

The file 'sfr52.inc' includes equates for 8052 special function registers and SFR bits that may be needed by some cross assemblers. The sfr52.inc file should be modified to suite your 8052 cross assembler since the equates required will vary from assembler to assembler. For example, one cross assembler I test with requires the equate for 'acc', and yet another cross assembler not only does not require it, but will generate an error if it is present. You may also need to edit the 'include' pseudo-op in the disassembly file if your cross assembler uses some other pseudo-op to include files (or edit the source file 'd52p2.c' and recompile).
It is best to start out with all the equates in sfr52.inc commented out, find out what undefined label errors your cross assembler generates, then uncomment the required equates in sfr52.inc.
This option is incompatible with the K option.

#### K Option (disassemble for Keil's A51 assembler)

Tells D52 to generate source code compatible with the older Keil A51 assembler.
NOTE: Newer versions of Keil's A51 assembler (tested with version 7.10) have come into compliance with the rest of the world. Do not use this option with newer versions of A51.

#### N Option (use C type operands)

Use this option to have the disassembler output hexadecimal operands using C notation, ie: 0xcd instead of the default 0cdh.

#### P Option (add dot in front of pseudo ops)

Some assemblers require pseudo operations to begin with a dot. Use this option to have the disassembler output ".equ" instead of "equ" and similar for org and other pseudo operations.

#### S Option (set string pseudo op)

This option tells the disassembler to generate the pseudo ops 'defb' and 'defw' instead of 'db' and 'dw' for those cross assemblers that may require this. Most cross assemblers understand 'db' and 'dw', so these are the defaults for the disassembler. Use this option for cross assemblers that do not recognize 'db' and 'dw'. If used in conjunction with the A option , the S option must preceed the A option on the command line.

#### T Option (trace and analyze code)

This option tells D52 to trace and analyze the 8052 code before disassembling it. D52 will attempt to determine which parts of the code are actually code, and which parts are ascii text, binary data, pointers, etc. While it does a reasonably good job of analyzing the code on most files, no program can do as good a job as a human programmer. A control file with the same name as the hex or bin file, but with an extension of '.ctl', will be created before the actual disassembly is performed. You can then edit the control file to correct any erroneous directives, or to add new directives.
Warning: Using this option will overwrite any control file that may already exist for the code file being disassembled. It is intended to be used on the first disassembly only.

#### U Option (upper case output)

Causes labels, symbols, mnemonics, etc to be output in upper case, for cross assemblers that may require upper case code. Comments, literal data values, strings, and other output are not affected by this option.

#### X Option (add hexadecimal offset to addresses)

This option causes the disassembler to add a hexadecimal offset to the address of every location in the code file. This may be useful for disassembling code that was read from the second (or subsequent) rom of a set of roms. For example, suppose that binary data was obtained from a set of 4K byte eproms (call them rom1 and rom2). Then the first file should be disassembled with the command line:

|  |  |  |  | d52 -d rom1

and the second should be disassembled with the X option:

|  |  |  |  | d52 -d rom2 x1000

The two files then can be combined into one and all references within the disassembled code will be to the correct addresses.
If given on the command line, the X option overrides any O directive in the control file.

#### Z Option (read cycle count file - d52 only)

Jan Waclawek has added code to generate cycle counts for all three disassemblers. In addition, d52 can read customized cycle count files for 8052 derivatives. See the Z directive for more information. Please read Jan's documentation in the 'cyclefiles' directory.

|  |  |  |  | d52 -zfilename

Many thanks to Jan for a great job!
Back to top

#### Control File Directives

Control directives tell the disassembler to treat specified areas of the code to be disassembled as something other than executable code. The user specifies control directives by editing (with any text editor) a control file with the same name as the file to be disassembled, but with a file extention of .ctl (eg: program.ctl to control the disassembly of the file program.hex or program.bin). A generic control file called 'generic.ctl' is provided to get the user started. Copy 'generic.ctl' to 'file.ctl' where 'file' is the name of the binary or Intel hex file to be disassembled, and modify as required based on the output of the disassembler. Then run the disassembler again to get a more readable disassembly of the code.
All directives consist of a character that specifies the type of data, followed by a hexadecimal number specifying the value or range of values of the data. In the case of a label or symbol directive, the hexadecimal number is followed by ascii text defining the label or symbol. See individual directives for examples. All directives must be in the first column of the line. Directives may be complete words, but only the first character is significant, ie:

|  |  |  |  | Label |  |  |  | 0 |  |  |  | reset |  |  |  |  |  |  |  |  |  | and
|  |  |  |  | looney |  |  |  | 0 |  |  |  | reset

will both generate the label "reset" for address 0. Note that they are not case sensitive.
Numerical values must be in hexadecimal and may optionally be preceeded by "0x". For example, a hexadecimal number may be entered as "1234" or "0x1234". Either will be interpreted as the number 1234H.
Everything following a semi-colon (;) is a comment and will be ignored by the disassembler.
Label and symbol directives differ in that a label refers to an address and a symbol refers to any 8 or 16 bit immediate data. Therefore an opcode such as

|  |  |  |  | mov |  |  |  |  |  | r2,#data

will cause the disassembler to search only the symbol table for a matching value whereas an opcode such as

|  |  |  |  | mov |  |  |  |  |  | dptr,#data

will cause the disassembler to search the label table first, and if no matching value is found, to then search the symbol table.
Symbols apply only to immediate data. To specify a symbol for an 8052 data memory location, use the R directive , or to force name substitution for an operand at a given address, use the X directive.
Single values are specified by entering just the value; ranges of values are specified by a start and stop address separated by a dash (-), or by a start address and count separated by a plus (+), ie:

|  |  |  |  | t 1000 |  |  |  |  |  |  | the data at address 1000H is ascii text.
|  |  |  |  | t 1000-1010 |  |  |  |  |  |  | the data from address 1000H to (and including) address 1010H is ascii text.
|  |  |  |  | t 1000+6 |  |  |  |  |  |  | ascii text starting at 1000H for 6 bytes.

Directives are processed in the order in which they are read from the control file. Specifying an area as ascii data and then later specifying it as data to be ignored (uninitialized data) will cause that area to not be disassembled at all. Care must be taken in specifying areas in the control file.

#### A Directive (address data)

Specifies that the address contains a word value corresponding to an address for which a label should be generated. For example, a vector table may be located at address 0x1000 containing four entries. The user can modify the control file by adding the following entry:

|  |  |  |  | a 1000-1007

This will cause the disassembler to generate the following output lines:

|  |  |  |  | dw |  |  |  |  | vec1
|  |  |  |  | dw |  |  |  |  | vec2
|  |  |  |  | dw |  |  |  |  | vec3
|  |  |  |  | dw |  |  |  |  | vec4

assuming that the control file also contains entries for the values found at those addresses to generate the labels vec1 through vec4. The addresses referenced will be flagged so that labels will be generated in the output file at those addresses.

#### B Directive (byte binary data)

Specifies that the data is to be interpreted as 8 bit binary data. For example:

|  |  |  |  | b 1000-1007

tells the disassembler that the data from address 1000H to 1007H should generate the line:

|  |  |  |  | db |  |  |  |  | 0,1,2,3,4,5,6,7

assuming that the data at address 1000H and up is 00H, 01H, etc.

#### C Directive (code data)

Forces the disassembler to interpret the data as executable code. This may be necessary because the disassembler skips over strings of 00H or ffH bytes that occur since they are unlikely to be real code. However, sometimes programmers insert several NOPs for timing purposes.

#### D Directive (define data type (label or symbol))

|  |  |  |  | d address [0 or label] |  |  |  |  | search label table only
|  |  |  |  | d address [1 or symbol] |  |  |  |  | search symbol table only
|  |  |  |  | d address [2 or none] |  |  |  |  | don't search either table

Forces the disassembler to search only the label or symbol table. This allows you to specify a label and a symbol for the same value. For example:

|  |  |  |  | mov dptr,#1234

would normally search only the label table assuming that the data refers to a code address. If the data is really a constant with the same value as a label, then

|  |  |  |  |  |  |  |  | d 1 address

will force the disassmbler to look only in the symbol table for the string that represents the value of the data. The address is the address of the opcode, not the code location of the data operand.
Note that the last parameter can be either a number (0, 1, or 2) or a word (label, symbol, none). If the last parameter is a word, only the first character is checked for L, S, or N, and is not case sensitive.

#### F Directive (SFR label definition)

Causes reference to an SFR (special function register) to generate a label for the specified SFR address. This is useful for naming SFR's for non-standard members of the 8052 family. For example, suppose that some manufacturer designs a new 8052 variant and decides to use address efH as a new special function register called 'NEWREG'. Then by adding:

|  |  |  |  | f ef newreg

to the control file, D52 will disassemble the opcodes f5 ef as:

|  |  |  |  | mov |  |  |  |  | newreg,a

instead of:

|  |  |  |  | mov |  |  |  |  | 0efh,a

SFR label names are limited to fifteen characters.

#### I Directive (ignore data)

Tells the disassembler to ignore a range of addresses that may be initialized by the input file. This is useful when the input file is a binary file generated by an eprom programmer that dumps the entire eprom space. The valid data from a 4K eprom might only be, say, 3K in length. By adding

|  |  |  |  | i c00-fff

to the control file, you tell the disassembler to not disassemble the data from address 0c00H to 0fffH.

#### K Directive (SFR bit definition)

As with the F directive , you can give a name to a new SFR bit. If a new variant of the 8052 family adds a new interrupt, for instance, its enable bit in the IE register might be bit 6. By adding:

|  |  |  |  | k ae newint |  |  |  |  |  |  |  | (ae is the address of IE.6)

you define bit 6 of the interrupt enable register to be 'ie.newint'. Like SFR label names, SFR bit names are limited to fifteen characters.

#### L Directive (label definition)

Defines a label to the disassembler. Labels are generated in the output disassembly file whenever a reference to the address is found and the label exists in the label table. Suppose that address 0000H contains the code 01 43 (ajmp 0043H). Then the entry

|  |  |  |  | l 43 start

in the control file will cause D52 to disassemble this code as:

|  |  |  |  | ajmp |  |  |  |  | start

rather than:

|  |  |  |  | ajmp |  |  |  |  | X0043

The code beginning at address 43H will then have the label 'start' in the label field rather than the label 'X0043'. See the entry for the S directive for an explanation of the difference between labels and symbols.

#### M Directive (bit addressable memory label)

Similar to the K directive , the M directive gives a name to a bit addressable memory location. Example:

|  |  |  |  | m 12 bitflag |  |  |  |  | (12h is the bit address of 22h.2)

would cause the bytes d2 12 to be disassembled as

|  |  |  |  | setb |  |  |  |  |  | bitflag

instead of

|  |  |  |  | setb |  |  |  |  |  | 22h.2

As with the K directive, names are limited to fifteen characters.

#### N Directive (suppress address label generation)

The disassembler will generate labels for addresses that are referenced by code such as

|  |  |  |  | mov |  |  |  |  |  | dptr,#6

If the operand represents a constant rather than an address, you can suppress the automatic generation of a label (X0006) for address 6h by entering

|  |  |  |  | n 6

in the control file. You'd want to make sure that address 6h isn't legitimately addressed by some other code before using this directive.

#### O Directive (add hexadecimal offset to addresses)

This directive causes the disassembler to add a hexadecimal offset to the address of every location in the code file. See the X option for details. It will be overridden by any X option specified on the command line. If the T option (trace and analyze code) is given on the command line, the O directive has no effect since any existing control file will be rewritten. In this case you must use the command line X option to specify an offset.

#### P Directive (patch inline code)

This directive is of dubious value, but has been added for anyone who might find it useful. The P directive is similar to the comment directive except that the user supplied string is patched into the output stream as code, not as a comment. You could, for instance, patch in a macro definition or an include statement. Patching in executable code is not a real good idea.

#### R Directive (register definition)

This directive specifies a name for an 8052 register. Direct accesses to registers will normally be disassembled as:

|  |  |  |  | mov |  |  |  |  |  | rb2r5,a

in the case of register 5 of register bank 2. If the user determines that register 5 of bank 2 is being used as a loop counter, for example, he can give it the name loop by adding:

|  |  |  |  | r 15 loop

to the control file, and the above code will be disassembled as:

|  |  |  |  | mov |  |  |  |  |  | loop,a

The R directive can assign a name to any internal memory location below the SFR address space.

#### S Directive (symbol definition)

Defines a symbol to the disassembler. Symbols are output to the disassembly file whenever the value is encountered in the input file and the symbol exists in the symbol table. The user can specify a symbol for a value by a line such as:

|  |  |  |  | s 20 space

Code which uses this value, such as:

|  |  |  |  | mov |  |  |  |  | a,#20h

will then be disassembled as:

|  |  |  |  | mov |  |  |  |  | a,#space

Labels and symbols differ in that a label applies to an address, whereas a symbol applies to any 8 or 16 bit immediate data. For code which can only refer to values, such as

|  |  |  |  | mov |  |  |  |  | a,#20h

only the symbol table will be searched for a matching value. For code which could refer to either an address or a value, such as:

|  |  |  |  | mov |  |  |  |  | dptr,#1234h

the label table will be searched first, and only if no matching value is found will the symbol table then be searched. This search behavior can be modified by use of the d directive or the x directive.

#### T Directive (text [ascii] data)

Forces the data in the range specified to be disassembled as text (ascii data). Thus the code: 48 69 20 74 68 65 72 65 at address 1000H will be disassembled as:

|  |  |  |  | db |  |  |  |  |  | 'Hi there' |  |  |  |  |  | or
|  |  |  |  | ascii |  |  |  |  |  | 'Hi there' |  |  |  |  |  | (command line option A used)

by putting the line:

|  |  |  |  | t 1000-1007

in the control file. Otherwise it would be interpreted as:

|  |  |  |  | orl |  |  |  |  |  | a,r0 |  |  |  |  |  | ; 1000 |  |  | 48 |  |  | H
|  |  |  |  | xrl |  |  |  |  |  | a,r1 |  |  |  |  |  | ; 1001 |  |  | 69 |  |  | i
|  |  |  |  | jb |  |  |  |  |  | 2eh.4,X106d |  |  |  |  |  | ; 1002 |  |  | 20 74 68 |  |  | th
|  |  |  |  | xrl |  |  |  |  |  | a,72h |  |  |  |  |  | ; 1005 |  |  | 65 72 |  |  | er
|  |  |  |  | xrl |  |  |  |  |  | a,t3 |  |  |  |  |  | ; 1007 |  |  | 65 ff |  |  | e.

which is unlikely to be what was intended by the original programmer. Data specified by this directive is not checked to verify that it really is ascii data--be careful.

#### W Directive (word binary data)

Specifies that the data is to be interpreted as 16 bit binary data. For example:

|  |  |  |  | w 1000-1007

tells the disassembler that the data from address 1000H to 1007H should generate the lines:

|  |  |  |  | dw |  |  |  |  | 0
|  |  |  |  | dw |  |  |  |  | 1
|  |  |  |  | dw |  |  |  |  | 2
|  |  |  |  | dw |  |  |  |  | 3

assuming that the data at address 1000H and up is 00H, 00H, 00H, 01H, 00H, 02H, etc. This differs from the A (address) directive in that the A directive also causes a reference to be made to the indirect address. In other words, if the data at address 1000H is 1234H, the A directive will cause a label (X1234) to be put in the output file at address 1234H, whereas the W directive will not.

#### X Directive (specify name for operand data)

Specify a name for an operand at a particular address. This is similar to the S directive except that it applies only to the given address. For example, if the symbol 'CR' is defined as 0dh, every instance of 0dh as an operand will have the symbol 'CR' substituted. It may be, however, that the value 0dh has a different meaning when used as an operand for a particular instruction. The X directive allows you to modify the interpretation of an operand at specific operand locations. Why not then use the X directive exclusively? Because that would force you to place an X directive in the control file for every instance in which that value appeared as an operand. The S directive, defined only once for an operand value, will substitute the symbol text for every occurrance of that operand value unless overridden by the X directive. Note that the address defined in the X directive is the address of the operand, not the address of the instruction. For example:

|  |  |  |  | X 102 loopinit

forces substitution of the text 'loopinit' for the operand located at address 102h. Therefore an instruction that should be interpreted as

|  |  |  |  | mov |  |  | r0,#loopinit

will not be disassembled as

|  |  |  |  | mov |  |  | r0,#CR

if the control file contains the above x directive, and also contains an S directive defining 0dh as 'CR', and the value of the operand for the mov instruction happens to also be 0dh.

#### Y Directive (specify name for operand data but suppress EQU generation)

This is similar to the X directive except that the disassembler will not generate an EQU statement for the operand value in the output file. This should be used when you want to specify a name for an operand that is an assembler pseudo-op such as LOW() or HIGH().

#### Z Directive (specify code for which to generate cycle count information)

Specify addresses for which cycle count information will be added in the disassembly file. Also see the Z option.
Please read Jan's documentation in the 'cyclefiles' directory.

#### # Directive (header comment string)

Defines a comment string to be output prior to disassembly at the specified address. For example:

            # 95
            # 95 Start of initialization
            # 95

in the ctl file would cause the output

            ;
            ; Start of initialization
            ;
                    clr  ea           ;0095     c2 af     B/

assuming that the code 'c2 af' was located at address 0x95. Since ASCII strings consume prodigious amounts of memory, it is wise to use this directive sparingly. It is, however, useful for marking blocks of code that have been identified in previous runs of D52.

#### ! Directive (inline comment string)

Defines a comment string to be output after disassembly at the specified address. For example:

            ! 95 Start of initialization

in the ctl file would cause the output

                    clr  ea           ;0095     c2 af     B/    ; Start of initialization

for the above example. Note that inline comments are only available for code and word data, and will do nothing if the data at the specified address is defined as data other than code or word data (ascii text, for example).
Back to top

#### A Note on Symbols, Labels and Names

An example will best explain the difference between labels, symbols, operand names and register names. Labels refer to program code locations, symbols refer to immediate operands, register names and operand names refer to data memory locations.
Given the hex or binary file produced from the follow source code:

|  |  |  |  | org |  |  | 30h
main |  |  |  |  | mov |  |  | a,30h
|  |  |  |  | mov |  |  | 30h,r0
|  |  |  |  | mov |  |  | r1,#30h
|  |  |  |  | sjmp |  |  | main
|  |  |  |  | end

and this control file:

l 30 | main |  | ; label for code address
x 33 | thirty |  | ; name for operand at address 33h
s 30 | alsothirty |  | ; symbol for immediate operand
r 30 | counter |  | ; name for data memory address (register) at 30h

D52 will produce the following output:

;
|  | org |  |  |  | 30h
;
main: |  | mov |  | a,counter |  | ; 0030 e5 30 |  | e0
|  | mov |  | thirty,r0 |  | ; 0032 88 30 |  | .0
|  | mov |  | r1,#alsothirty |  | ; 0034 79 30 |  | y0
|  | sjmp |  | main |  | ; 0036 80 f8 |  | .x
;
counter |  | equ |  | 30h
alsothirty |  | equ |  | 30h
thirty |  | equ |  | 30h
;
|  | end
;

Note that the label, symbol, register name, and operand name all have the same value: 30h. But the operand name directive ( x directive) in the control file specifies the address of the operand (in this case 33h), and the other three control file directives refer to the value of the operand. The x directive allows you to use a different name for the same value (unlike a symbol), so that, for example, an operand value of 0dh in one place can be disassembled with the name 'CR' and in another place as, say, 'loop_init_count'.

#### Format of Output File

The output file for D52 (extention '.d52') contains 8052 instructions and pseudo ops in a format that should be acceptable to any 8052 cross assembler. When assembled, the source file should produce an Intel hex file or binary file that is identical to the original. Identical, in this case, means that the code is the same, not that it necessarily has the same format. The number of bytes in each line of the hex file may differ from the original depending on whether the original was produced by an assembler or was read from an eprom. Each output line is in the following format:

|  |  |  |  | LABEL: |  |  | OPCODE |  |  | OPERANDS |  |  | ; COMMENT

The label field will be generated only if the address of the code is referenced by some other code (a call, for instance), or if the user has specified a label for that address in the control file. The comment field is only generated if the user specifies the D option on the command line. Comments begin with a semicolon and are followed by the hexadecimal address of the instruction, the hex value of the byte(s) for the instruction, and finally by the ascii representation of the instruction byte(s). For example:

|  |  |  |  | X004f: |  |  |  | orl |  |  |  | p3,#0ffh |  |  |  | ; 004f |  |  |  | 43 b0 ff |  |  |  | C0.
|  |  |  |  | label |  |  |  | opcode |  |  |  | operands |  |  |  | comment

Several things should be noted in this example. The label is 'X' followed by the address of the instruction in four hex digits. This type of label is created by the disassembler when some other code references the address. If the user specifies a label name for the address in the control file ('what' for example), the generated code becomes:

|  |  |  |  | what: |  |  |  | orl |  |  |  | p3,#0ffh |  |  |  | ; 004f |  |  |  | 43 b0 ff |  |  |  | C0.

If the user were to specify the symbol 'ones' for the value 0ffH, the output would then become:

|  |  |  |  | what: |  |  |  | orl |  |  |  | p3,#ones |  |  |  | ; 004f |  |  |  | 43 b0 ff |  |  |  | C0.

Also note the ascii representation of the instruction bytes. Bit 7 is forced to zero so that ascii with the high bit set can be viewed (b0H in the example becomes 30H, which is ascii '0'). Any code which is not printable ascii (a control code, for example) is output as a period. This is the case for the byte 0ffH above.
The comment field starts at a different position in the output line depending on the type of data in the input file. For normal executable code, the comment field starts in column 32; for hex data it starts at column 49, and for ascii data it starts in column 56. For many programs, this makes for a more readable source file, but if there is a mix of data types in a short range of addresses, this can lead to some strange looking formatting. The user may want to correct this with a text editor in the final disassembly before modification and reassembly.
Back to top

#### Summary

D52 is distributed under the GNU General Public License. See the file COPYING for details. D52 versions 3.1 and higher are a continuation of the earlier disassembler named D51.
D52 allows the user to specify how code should be disassembled via a control file that defines given areas of the code as ascii text, binary data or other types of non-executable code. By an iterative process of disassembly, control file modification, and further disassembly, the user can obtain a very readable source file that can then be modified and re-assembled by a cross assembler. Several public domain cross assemblers are available.
I've encountered several problems when reassembling the output of D52. Almost all are due to the cross assembler not recognizing SFRs of some of the newer or more exotic 8052 variants. The D52 tables include names for all SFRs that I'm aware of as of May 1995 (there are likely some that I'm not aware of). Such errors might be corrected just by defining a symbol for the SFR in the control file (see the F directive ), but this depends on whether your cross assembler will accept it as a valid operand. If all else fails, replace the offending instruction with a 'db' pseudo op and put the mnemonic and operand in a comment. A similar problem is the assembler not being able to handle a bit addressable SFR address; the only solution I see to this is to use a 'db' pseudo op. All other problems I've seen (not many) have been due to disassembling data as code; this is easily corrected by modifying the control file to specify the correct data type.
Many thanks to numerous beta testers who have made invaluable suggestions for improvement and found more bugs than I care to think about. Also thanks to all the users who have, over the years, also made significant contributions to the betterment of D52. Any remaining deficiencies are solely my fault.

#### Summary of command line options and control file directives

Command line options:

- A - Change db/defb pseudo op to 'ascii' macro for text
- B - Force read of binary file (.bin extention)
- D - Add address and data info in comment field
- H - Force read of Intel hex file (.hex extention)
- I - Add statement to include file 'sfr52.inc' in output file
- K - Disassemble for older Keil A51 assembler
- N - Output C style hexadecimal operands
- P - Add a dot '.' to beginning of pseudo operation codes
- S - Change db and dw pseudo ops to defb and defw
- T - Trace and analyze code before disassembly
- U - Output labels, mnemonics, etc in upper case
- X - Add hexadecimal offset to all program locations
- Z - Read cycle count file (d52 only)

Control file directives:

- A - Specifies that words in program space are addresses
- B - Data is 8 bit binary
- C - Program space is executable code
- D - Force search of only label table or only symbol table for operand name
- F - Specify SFR label
- I - Ignore data (uninitialize program space)
- K - Specify label for SFR bit
- L - Define label
- M - Specify label for bit addressable memory
- N - Suppress generation of address label
- O - Add hexadecimal offset to all program locations
- P - Patch inline code
- R - Define register name
- S - Define symbol
- T - Specify ascii text
- W - Data is 16 bit binary
- X - Specify name for a specific operand
- Y - Specify name for a specific operand but do not generate an EQU statement
- Z - Specify addresses for which to generate cycle count information
- # - Define a header comment string
- ! - Define an inline comment string

Back to top

#### 8052 Register Maps

Addresses of 8052 registers:

Bank | R0 | R1 | R2 | R3 | R4 | R5 | R6 | R7
--- | --- | --- | --- | --- | --- | --- | --- | ---
0 | 00 | 01 | 02 | 03 | 04 | 05 | 06 | 07
1 | 08 | 09 | 0A | 0B | 0C | 0D | 0E | 0F
2 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17
3 | 18 | 19 | 1A | 1B | 1C | 1D | 1E | 1F

Addresses of 8052 Special Function Registers:

Address | Symbol | Name
--- | --- | ---
80 | P0 | Port 0
81 | SP | Stack Pointer
82 | DPL | Data Pointer (low byte)
83 | DPH | Data Pointer (high byte)
87 | PCON | Power Control
88 | TCON | Timer/Counter Control
89 | TMOD | Timer/Counter Mode
8A | TL0 | Timer/Counter 0 (low byte)
8B | TL1 | Timer/Counter 1 (low byte)
8C | TH0 | Timer/Counter 0 (high byte)
8D | TH1 | Timer/Counter 1 (high byte)
90 | P1 | Port 1
98 | SCON | Serial Port Control
99 | SBUF | Serial Data Buffer
A0 | P2 | Port 2
A8 | IE | Interrupt Enable
B0 | P3 | Port 3
B8 | IP | Interrupt Priority
D0 | PSW | Program Status Word
E0 | ACC | Accumulator
F0 | B | B Register

Back to top

#### Bit Addressable Special Function Registers

Address | Symbol | Bit name | Function
--- | --- | --- | ---
80-87 | P0.0-7 |  | Port 0
88 | IT0 | TCON.0 | External Interrupt 0 Type Control
89 | IE0 | TCON.1 | External Interrupt 0 Edge Control
8A | IT1 | TCON.2 | External Interrupt 1 Type Control
8B | IE1 | TCON.3 | External Interrupt 1 Edge Control
8C | TR0 | TCON.4 | Timer 0 Run Control
8D | TF0 | TCON.5 | Timer 0 Overflow Flag
8E | TR1 | TCON.6 | Timer 1 Run Control
8F | TF1 | TCON.7 | Timer 1 Overflow Flag
90-97 | P1.0-7 |  | Port 1
98 | RI | SCON.0 | Serial Receive Interrupt Flag
99 | TI | SCON.1 | Serial Transmit Interrupt Flag
9A | RB8 | SCON.2 | Serial Receive Bit 8
9B | TB8 | SCON.3 | Serial Transmit Bit 8
9C | REN | SCON.4 | Serial Receive Enable
9D | SM2 | SCON.5 | Serial Port Mode Specifier
9E | SM1 | SCON.6 | Serial Port Mode Specifier
9F | SM0 | SCON.7 | Serial Port Mode Specifier
A0-A7 | P2.0-7 |  | Port 2
A8 | EX0 | IE.0 | Enable External Interrupt 0
A9 | ET0 | IE.1 | Enable Timer 0 Interrupt
AA | EX1 | IE.2 | Enable External Interrupt 1
AB | ET1 | IE.3 | Enable Timer 1 Interrupt
AC | ES | IE.4 | Enable Serial Port Interrupt
AF | EA | IE.7 | Enable Interrupts
B0-B7 | P3.0-7 |  | Port 3
B8 | PX0 | IP.0 | External Interrupt 0 Priority
B9 | PT0 | IP.1 | Timer 0 Interrupt Priority
BA | PX1 | IP.2 | External Interrupt 1 Priority
BB | PT1 | IP.3 | Timer 1 Interrupt Priority
BC | PS | IP.4 | Serial Port Interrupt Priority
D0 | P | PSW.0 | Parity
D2 | OV | PSW.2 | Overflow Flag
D3 | RS0 | PSW.3 | Register Bank Select Bit 0
D4 | RS1 | PSW.4 | Register Bank Select Bit 1
D5 | F0 | PSW.5 | Flag 0 (general purpose flag)
D6 | AC | PSW.6 | Auxiliary Carry Flag
D7 | CY | PSW.7 | Carry Flag
E0-E7 | ACC.0-7 |  | Accumulator Bits
F0-F7 | B.0-7 |  | B Register Bits

Back to top

#### Addresses of Bit Addressable Memory Locations

Address | Memory location
--- | ---
00-07 | 20.0 - 20.7
08-0F | 21.0 - 21.7
10-17 | 22.0 - 22.7
18-1F | 23.0 - 23.7
20-27 | 24.0 - 24.7
28-2F | 25.0 - 25.7
30-37 | 26.0 - 26.7
38-3F | 27.0 - 27.7
40-47 | 28.0 - 28.7
48-4F | 29.0 - 29.7
50-57 | 2A.0 - 2A.7
58-5F | 2B.0 - 2B.7
60-67 | 2C.0 - 2C.7
68-6F | 2D.0 - 2D.7
70-77 | 2E.0 - 2E.7
78-7F | 2F.0 - 2F.7

Back to top