DHC11 Tutorial

    This is a tutorial for the DHC11 Motorola 68HC11 Disassembler. Reference is also made to the author's ASHC11, a 68HC11 Macro Assembler. The tutorial is heavily oriented to disassembling a GM ECU binary (an EPROM found in a GM vehicle's ECU, or engine management computer)
Text that you write is shown in red and console output that the disassembler produces is shown in dark blue italics. File output that the disassembler produces is shown in normal dark blue.

Initially, the bin for disassembly (called BJKS8010.BIN in the examples) is identified and a control file BJKS is created with the following minimal information describing the input file and the name of the output file.

; This control file is called BJKS
input   bjks8010.bin   ;this is the binary input file
output  bjks.DIS       ;this is the disassembly source/listing file
At a Dos prompt the command c:\>dhc11 bjks -a is given. The -a switch forces addresses in the output. The resulting console output is shown below:
DHC11 - 68HC11 Disassembler v1.00 (c) Copyright 2000 Tech Edge Pty. Ltd.

Input file: bjks8010.bin
Input file bjks8010.bin has 32768 bytes ($8000).
Output file: bjks.DIS
Code resides from $8000 to $FFFF ($8000 bytes).
No entry point - defaulting to disassembly from $9006 (reset vector at $FFFE).
Entry point $1000 outside ROM image (ref. from PC = $916E).
Indexed Call/Jump at $D3A2, may require a vector table.
Pass 1 found 316 new entry points.
Pass 2 found 93 new entry points.
Pass 3 found 0 new entry points.
Total of 3 iteration(s) to find all code.
This shows that the file was read into memory and automatically located from $8000 through to $FFFF. As no initial entry point was supplied, the reset vector at $FFFE was used and this contained the address $9006. The first two passes found 316 + 93 entry points, and the third found no more, so DHC11 stopped seeking more code and ran the code/data output pass.

Looking at the output file bjks.dis we find there is a lot of data that should probably be code. We remember that the 68HC11 has a few vectors at the top of memory. Inspecting the file we see:

FFC9            fill    $00, 39
FFF0            db      $60, $00, $93, $69, $B3, $34, $60, $00, $90, $02
FFFA            db      $90, $00, $90, $04
FFFE    LFFFE:  dw      L9006
This indicates that there are probably 8 vectors. The easiest way to tell the disassembler this is via the control file line:
vectors $fff0 8 hc11vec hc11vector
Doing this, and running DHC11 again, but this time with the -ov switch to overwrite the old output file bjks.dis, we get the following
** Symbol "hc11vec_00" is already Install at $6000 ("hc11vec_03" requested)
Entry point $1000 outside ROM image (ref. from PC = $916E).
Indexed Call/Jump at $94BB, may require a vector table.
Entry point $1009 outside ROM image (ref. from PC = $94CC).
Indexed Call/Jump at $D20A, may require a vector table.
Indexed Call/Jump at $D3A2, may require a vector table.
Pass 1 found 1466 new entry points.
Pass 2 found 132 new entry points.
Pass 3 found 3 new entry points.
Pass 4 found 0 new entry points.
Total of 4 iteration(s) to find all code.
We now find more code (1466 + 132 + 3 entry points) and it takes an extra pass. We also find we now have two messages indicating indexed call instructions were encountered. Looking at the code for the two address ($D20A and $D3A2) we find the code:
D1EA    LD1EA   ldaB    L01BE
D1ED            cmpB    #$0A
D1EF            bhi     LD235
D1F1            bset    L005E, #%00100000
D1F4            bset    L005D, #%00000100
D1F7            staB    L01B9
D1FA            lslB
D204            ldX     #$D249
D207            aBX
D208            ldX     0, X
D20A            call    0, X
....            ...
D39E    LD39E   ldY     L01B2
D3A2            call    0, Y
The first indexed call is easy, as the address of a table (at $D249 is supplied, and it looks like there are only 11 entries (register B is compared against $0A and branches if higher, so 0..10 => 11) Also, knowing a bit about the application, we may know that some code is called at fixed time intervals from a timer interrupt, and calls successive procedures listed in a table. So we can add the command:
vectors $D249 11 loop timevectors
Forgetting about the second indexed call for the moment, we run DHC11 again and find another indexed call
Indexed Call/Jump at $94BB, may require a vector table.
vectors $D249 11 loop timevectors
And again we look at the code and discover a vector table at $94DB, and it seems to have 16 entries as the code shows register B is masked to a 4 bits (= 16 entries):

94B2            andB    #%00001111                 <-- mask to 4 bits here
94B4            ldX     #$94DB                     <-- base table address here
94B7            lslB
94B8            aBX
94B9            ldX     0, X
94BB            call    0, X                       <-- call one of 16 address

So, not being sure what these vertors are for, we add the following command and
run DHC11 again:

vectors $94db 16 some somevectors
Pass 1 found 2138 new entry points.
Pass 2 found 130 new entry points.
Pass 3 found 3 new entry points.
We don't get any more indexed jumps, but we now have (2138 + 130 + 3 = 2271) entry points being automatically found. So, we look through the code generated by DHC11 and we find a large slab of dbs at $cbc3, so wee look through the code for references to this address and we find this adress is used as a parameter in a call:
C2DF    LC2DF   ldX     #$CBC3                     <-- load here
C2E2            brset   L0059, #%00000100, LC2EF
C2E6            brset   L0074, #%00100000, LC2EF
C2EA            ldX     #$CBD4
C2ED            jr      LC2F5
C2EF    LC2EF   addA    #$0A
C2F1            bcc     LC2F5
C2F3            ldaA    #$FF
C2F5    LC2F5   call    LC9B5                      <-- call here
Looking through the code for the call's target address of $c9b5 we find many calls to this address using the IX register as a parameter. Looking at the code at $c9b5 we find some kind of a table looup routine. Now, here's where we could slog it out and try to work out what's happening, but a few people have already done some of the hard work, including ECMguy at http://ecmguy.tripod.com/, whos disassembly of the BUA binary can be found (in text format) at:


A quick (!) look at the BUA disassembly will show that a possible name for the function at $C9B5 could be P4LKUPQ. We'll choose the label Lookup2d16 (remembering that most assemblers would not like a label starting with a number) because it better reflects its function, and we are not limited to a certain number of characters for our labels. We'll also add a few more labels we can assign just by looking at the BUA disassembly and comparing code around the Lookup2d16 area.

entry $c9aa Lookup2d_nooff  ;2D Lookup with offset
entry $c9b1 Lookup2d        ;2D Lookup
entry $c9b5 Lookup2d16      ;2D Lookup with tables spaced at 16
entry $c9c9 Interpol        ;interpolate between two 8 bit values
entry $c9d2 Lookup3d        ;3d Lookup (2 variables)
entry $ca74 mul16x16        ;multiply 16 x 16
We could spend a bit of time comparing routines and assigning labels for those routines that are common. For the case where we know a bit about the software or hardware, but don't have a disassembly to help, we must do some more investigation. The ALDL data stream can help us. The ALDL output of most ECMs is reasonably well documented, so we need to look for the ALDL code to help us identify the location, in memory, where the data is stored. This may give us the memory locations for many variables and tables.

The P4 series of GM ECUs assigns location

$4007   Transmit status register
$4008   Receive status register
$4009   Receive data register
$400A   Transmit data register

Last Updated 15 May 2000

Statistics by   www.digits.com
Shows approximate hits since 15 May 2000.

This document is copyright © 2000, Tech Edge Pty. Ltd.
Author P. Gargano

Home | e-mail DHC11 Feedback | Copyright