Download as pdf or txt
Download as pdf or txt
You are on page 1of 6

The Wayback Machine - https://web.archive.org/web/20170911223915/http://www.forzavx.com:80/gecu/reveng/tutorial-dasm.

html

Tutorial for “reverse-engineering” the Weber Marelli IAW ECUs


(as found in the Lancia Delta Integrale)
The grale-ECU (GECU) tools are provided free of charge but without warranty or support. Here I describe how I use them.

Since buying my Lancia Delta Integrale (non-Evo 16V with ABS) I find this car already has a very advanced engine management ECU controlling
spark, fuel and boost. My ECU is labeled WH4W.08/90K-9B. I have archived more information about the basic hardware of the system on the
tools page GECU HARDWARE INFORMATION section..

Being in a country where these cars were not sold from new, local support is non-existent so I need to do everything myself. Since the ECU
appears to be at least as advanced as systems like megasquirt I figured it would be worthwhile to figure it out rather than replacing it.

1. Create a working directory and get the EPROM binary


Create a directory (eg. c:\gecu) on your PC and download the EPROM binary there (right click on the link and save in new directory).
The ECU operating instructions (code) and configuration tables (maps) are contained in the same EPROM (27128 in the case of my ECU). This is
what we are trying to reverse-engineer. Although both the code and maps can be changed to affect the engine performance the ECU is not
designed for in-service upgrade by FLASH re-programming (more on this in the tuning tutorial). In general the binary file can be extracted from
the stock EPROM by plugging it into an EPROM reader or you might find it in the PROGRALE download area.

2. Download the GECU tools

Download these tools as a single zip file into the gecu directory you created in step 1 and extract them there.
These are the software tools necessary to interpret what’s in the EPROM. If for some reason you don’t have the ability to unzip then download
them one-by-one from the tools page GECU REVERSE ENGINEERING section.

You should now have a folder with the following files in it:
1. dasm.bat
2. dhc11.exe
3. diss.bat
4. gecu.bin
4: gecuadd.exe
5. gecudctl.txt
6. gecudiss.txt
7 gecuparse.exe

3. Run the 1st pass of the disassembler

Open a file explorer window and navigate to the working directory (eg. c:\gecu). Run the 1st pass of the disassembler (double click on diss.bat).
A DOS window will temporarily open then close. I have redirected all output to log files so we can just do stuff from the windows environment
rather than having to go to DOS. This should have created 4 new files:
1. diss.log (this file tells you the results of running the diss batch file.)
2. gecu.cmt (this is an empty comment file needed for later)
3. GECU.DIS (this is the raw disassembled ECU file - but we won't be using this)
4. gecu.txt (this will eventually be the commented disassembly file - but right now its empty)

4. Now the real work starts !

Run the disassembler using dasm.bat (double click dasm.bat). A DOS window temporarily opens and closes with the results in the log file
dasm.log.

Now the process of converting from a binary to something that is human readable begins. The process of disassembling the code can be aided in 2
ways;
1. Whenever we learn where things are in the memory map (internal or external RAM or internal or external device) we create an entry in
the disassembler control file so that the next time we run the dasm batch file we'll have an easier to understand english language name rather
than a number.
2. When we figure out how things are working in the code we can add comments to the commented disassembly file so we'll remember what
was going on the next time we look at this section of code (or when it happens to be used again - say as a subroutine)

This will be an iterative process until we've figured out the whole EPROM binary. That's all there is to it !

5. Background - lets look at each tool in detail

gecuparse

gecuparse usage: gecuparse input_commented_file output_comment_only_file


This tool strips comments from the commented disassembly file and saves them in a comment file. In general what it does is:
open commented disassembly file and search line-by-line for the “comment” character. For various reasons I have chosen to use the “*”
character to signify the start of a comment that should be saved
save the entire line that has the comment. I save the whole line so that I can use the line number to re-insert the comment into the new
disassembly file

gecuadd

useage: gecuadd input_comment_file input_disassembler_file output_merged file


This tool merges comments from the comment file with the same line in the disassembler file to create the merged commented disassembler file. In
general what it does is:

open the comment file and get the line number for the next comment
open the disassembler file and copy it to the commented disassembler file until you come to the line number of the next comment
add the comment field (the “*” and everything after it) to the end of the line

Note the following restrictions:

comments must be on a single line


comments can not be on a line without code

dhc11

useage: dhc11 disassembler_control_file -a -op –ov


The best description of this tool is the tutorial on the Tech Edge web site. I will explain how I use it.
I use the following command line options:

-a: Show addresses on left of each disassembled line (I need this for the comments)
-op: Show opcodes for instructions disassembled
-ov: Forces output file to be overwritten if it already exists

gecudiss.txt & gecudctl.txt

The disassembler control file(s) deserves a little extra detail. The most important thing that happens in the control file is the creation of the
memory map for the disassembler. In the 1st pass of the disassembler (diss.bat) we don’t know anything about the system so all that we have
in there is the input and output file names. Have a look at gecudiss.txt and here’s what you’ll find:
input gecu.bin
output gecu.dis

Note that the disassembler uses “;” for its comment character. If you want to add comment information to the control file you have to use the
; character. Everything after the “;” is ignored.

Control file commands

The following commands, all within the control file, tell the disassembler information about the binary image it will process. The more
information that can be determined and supplied here, the better the resulting disassembly will be. Optional parameters are enclosed in
square [ ] brackets.

Label <addr> <name> Assign a label <name> to address <addr>.


Provide a code entry point <addr> with optional label <name>. The code seeking algorithm
scans memory for these locations, and automatically adds new entry points as branch and
Entry <addr> [<name>]
call instructions are encountered. When no new entry points are added in a single pass, then
the disassembler has completed the code seek phase
Define a pointer to to an (indirect) address. An indirect address is a 16 bit quantity (ie. word,
or two bytes) that is used by the processor to form a target (jump or call) address. The word
at memory address <addr> points to an address that is tagged as an entry point, and the
Indirect <addr> [<name> [ <here>]]
optional <name> is the label for this address. And finally, <here> will be tagged as a data
word. The ordering of labels was chosen to maintain compatibility with existing
disassemblers.
Define a range of indirect addresses, as would be produced by a jump table, or list of
procedure addresses. The number of data words (or vectors) is defined by <count>. The
Vectors <addr> <count> [<name> [<here>]] optional <name>, if supplied, is used to create a label, for each indirect address, of the form
<name>_NN where NN starts from 00. The optional <here> is the address (ie. <addr>) of the
word table. Note that NN is one less than <count>.
Bytes <addr> <count> [<name>] Define a byte table at <addr> of <count> length.
Words <addr> <count> [<name>] Define a word table at <addr> of <count> length

Mnemonics

And finally on the disassembler topic please note the following differences about the way the Tech Edge disassembler presents the
mnemonics compared to those specified by Motorola for the processor.
DHC11's Mnemonics Motorola's Function Performed
call JSR Call
callr BSR Call Relative (short call)
cmpD, cmpX cmpY CP? Compare (16 bit register)
decX, decY, decS DE? Decrement (16 bit register)
di SEI Disable Interrupts
ei CLI Enable Interrupts
incX, incY, incS IN? Increment (16 bit register)
jr BRA Jump Relative (short jump)
push, pushB, pushX, pushY PSH? Push on to stack
popA, popB, popX, popY PUL? Pop off stack
ret RTS Return (from subroutine)
reti RTI Return From Interrupt
xorA, xorB EOR? eXclusive Or

As you can see, DHC11's mnemonics use, at most, one extra character, but this makes their meaning much clearer, and is closer to a
majority of other assembler syntaxes. In addition, the mnemonics are displayed in a mixed case that is designed to highlight the registers use
by the instruction. For example, LDA, the Load A instruction is displayed as ldA to emphasise that the A register is used in this ld
instruction. The tAB and xgDY are examples of instructions that use two registers in the one mnemonic.

6. Overview of disassembly process

Now that we know the details of each tool lets have a look at each element in the process

dasm.bat - the disassembler batch file

This batch file does the following:

parse any comments from the commented disassembler listing (gecu.txt)


disassemble the binary file using the disassembler control file (gecudctl.txt)
add the comments to the disassembler output file creating a new commented disassembler file (gecu.txt)

dasm.log - the disassembly log file

The log file records the messages from the comment parser and adder and the disassembler. An initial log file might look like this:

GECUparse - Comment Parser v1.1 (c) Copyright 2008 www.forzavx.com

Input file: gecu.txt


Output file: gecu.cmt
Total of 0 comments parsed.

DHC11 - 68HC11 Disassembler v1.1 (c) Copyright 2000 Tech Edge Pty. Ltd.

Input file: gecu.bin


Input file gecu.bin has 16384 bytes ($4000).
Output file: gecu.dis
Code resides from $C000 to $FFFF ($4000 bytes).
** Symbol "RESET_00" is already Install at $C000 ("MIR_irq_00" requested)
** Symbol "RESET_00" is already Install at $C000 ("SIR_irq_00" requested)
Indexed Call/Jump at $C3DF, may require a vector table.
Pass 1 found 1336 new entry points.
Pass 2 found 0 new entry points.
Total of 2 iteration(s) to find all code.

GECUadd - Comment Adder v1.1 (c) Copyright 2008 www.forzavx.com

Input comment file: gecu.cmt


Input disassembly file: GECU.DIS
Output file: gecu.txt

Total of 0 comments added.

And now for the meat of the disassembly process

gecudctl.txt - the disassembler control file


This file tells the disassembler to use an understandable name for various parts of the memory map. Lets look at it a piece at a time.

The input / output file spec:


; This control file is called gecudctl.txt
;
input gecu.bin ;this is the binary input file
output gecu.dis ;this is the disassembly source/listing file

The next section is the internal memory mapped devices of the MC6803U4 processor
; MEMORY MAP

; --- INTERNAL DEVICES ---

; 0x0000 to 0x001F internal registers (see MC6803U4 datasheet)


label $0000 PORT1_DDR
label $0001 PORT2_DDR
label $0002 PORT1_DATA
label $0003 PORT2_DATA

label $0008 TMR_CSR


label $0009 TMR_CNTd ; 16 bit
label $000B TMR_OCR1d ; 16 bit
label $000D TMR_ICR1d ; 16 bit

label $0010 SCI_RMCR


label $0011 SCI_TRCSR
label $0012 SCI_RX
label $0013 SCI_TX

label $0015 TMR_CNTAd ; 16 bit - alternate to TMR_CNT (TOF safe)


label $0017 TMR_CR1
label $0018 TMR_CR2
label $0019 TMR_SR
label $001A TMR_OCR2d ; 16 bit
label $001C TMR_OCR3d ; 16 bit
label $001E TMR_ICR2d ; 16 bit

The next section is the internal RAM variable declarations. I've named a few that were easy to find since they are part of the serial command
interface.
; 0x40 to 0xFF internal RAM
; insert symbol names here
;
label $0048 cmd_throttle_valve_angle
label $0049 cmd_air_temp
label $004A cmd_water_temp
label $004B cmd_injection_duration_msb
label $004C cmd_injection_duration_lsb
label $004D cmd_ignition_advance

label $0054 cmd_injection_timing_angle


label $0055 cmd_co_trimmer

label $005F cmd_battery_voltage


label $0093 cmd_vae_duty_cycle_msb
label $0094 cmd_vae_duty_cycle_lsb

label $00A7 cmd_param_12


label $00A8 cmd_param_13

label $00AF cmd_param_14

label $00B5 cmd_engine_period_msb


label $00B6 cmd_engine_period_lsb

label $00CE cmd_uniram_1


label $00CF cmd_uniram_2

label $00D7 cmd_intake_pressure


label $00D8 cmd_uniram_3

The next section is the external RAM variable declarations. Coincidentally a few are also part of the serial command interface.
; --- EXTERNAL DEVICES ---

; 0x1800 to 0x1FFF external RAM (6116 2KX8 SRAM)


; insert symbol names here
label $1819 cmd_intake_pres2
label $1821 cmd_uniram_s

label $1826 int_error_1


label $1827 int_error_2
label $182F cmd_param_17msb
label $1830 cmd_param_17lsb

The next section identifies the external memory mapped devices


;0x2000 to 0x2006 (MC6840 timer)
label $2000 ETMR_WCR3_1
label $2001 ETMR_WCR2_RSR
label $2002 ETMR_TCR1
label $2004 ETMR_TCR2
label $2006 ETMR_TCR3

;0x4000 to 0x4002 (MC14442 A to D converter 8 bit with input mux)


; configured as 16 bit registers
label $4000 ADC_DATA
label $4002 ADC_CTRL

This next section shows some examples of labeling code addresses as a jump table, parameter list and vector table. The first table was found as
part of the self-test commands, the next table is the list of memory addresses that are dumped as the diagnostic command responses and finally the
vector table at the top of memory again based on the MC6803U4 CPU.
; External EPROM (27128 - 16Kx8)
; 0xC000 to 0xFFFF

; jump table
; vectors $C3F9 5 jump jumpvectors ; works but doesn't give desired result
indirect $C3F9 DIAG_test_fuel_pump DIAG_jump_vectors
indirect $C3FB DIAG_test_injectors
indirect $C3FD DIAG_test_coil
indirect $C3FF DIAG_test_vae
indirect $C401 DIAG_test_overboost

; ECU parameter table


words $ED65 24 CMD_REPLY_TABLE
;
; vector table (see MC6803U4 datasheet)
vectors $FFFE 1 RESET RESETvector
vectors $FFF0 1 SCI_irq SCIvector
vectors $FFF2 1 TOF_irq TimerOverflowFlagvector
vectors $FFF4 1 OCF_irq OutputCompareFlagvector
vectors $FFF6 1 ICF_irq InputCompareFlagvector
vectors $FFF8 1 MIR_irq MaskIntReqVector
vectors $FFFA 1 SIR_irq SwIntReqvector
vectors $FFFC 1 NMI_irq NMIvector

gecu.txt - the commented disassembler file

This file is where we look to see what the ECU is doing to our car. We haven't inserted any comments yet so if we look at the log file (dasm.log)
we will see that it found 0 comments. The file is too large to list here but lets have a look at a few key sections and add a couple comments. To
look at the file I find it easiest to use notepad. Unless you've changed the default behavior of windows notepad will automatically open the file
when you double-click on gecu.txt.

;
; DHC11 - 68HC11 Disassembler v1.1 (c) Copyright 2000 Tech Edge Pty. Ltd.
;
; http://www.techedge.com.au/utils/dhc11.htm
;
;
; Disassembly of gecu.bin - from $C000 to $FFFF
;
*** Internal Registers as we defined in the disassembler contol file
PORT1_DDR = $0000
PORT2_DDR = $0001
PORT1_DATA = $0002
PORT2_DATA = $0003
TMR_CSR = $0008
TMR_CNTd = $0009
TMR_OCR1d = $000B
TMR_ICR1d = $000D
SCI_RMCR = $0010
SCI_TRCSR = $0011
SCI_RX = $0012
SCI_TX = $0013
TMR_CNTAd = $0015
TMR_CR1 = $0017
TMR_CR2 = $0018
TMR_SR = $0019
TMR_OCR2d = $001A
TMR_OCR3d = $001C
TMR_ICR2d = $001E
L0040 = $0040
L0041 = $0041
L0042 = $0042
L0043 = $0043
L0044 = $0044
L0045 = $0045
L0046 = $0046
L0047 = $0047
*** Internal RAM variables as we defined in the disassembler control file
cmd_throttle_valve_angle = $0048
cmd_air_temp = $0049
cmd_water_temp = $004A
cmd_injection_duration_msb = $004B
cmd_ignition_advance = $004D
<snip>
*** Start of code execution (notice code label)
C000 RESET_00:
C000 8E 00 FF ldS #$00FF
C003 4F clrA
C004 B7 18 12 staA L1812
C007 86 D6 ldaA #$D6
*** Instruction with a reference to a variable as defined in the disassembler control file
C009 97 02 staA PORT1_DATA
<snip>
*** This section is where the internal self test is activated - Lets add some comments !
C3C9 C4 7F LC3C9 andB #%01111111
C3CB C1 05 cmpB #$05
C3CD 24 AC bcc LC37B
C3CF 37 pushB
C3D0 BD ED F6 call LEDF6
C3D3 33 popB
C3D4 86 1A ldaA #$1A
C3D6 97 11 staA SCI_TRCSR
*** Go to this section in the listing file and type in the * and comment
C3D8 CE C3 F9 ldX #$C3F9 * load the base address of the diagnostic jump table
C3DB 58 lslB * double diagnostic test code to account for double word offset in table
C3DC 3A aBX * add offset to jump table base
C3DD EE 00 ldX 0, X * get jump address from table
C3DF AD 00 call 0, X * start execution from jump address
C3E1 86 0A LC3E1 ldaA #$0A
C3E3 97 11 staA SCI_TRCSR
C3E5 4F clrA
C3E6 5F clrB
C3E7 DD D3 stD L00D3
C3E9 96 D5 ldaA L00D5
C3EB 84 7C andA #%01111100
C3ED 97 D5 staA L00D5
C3EF C6 FF ldaB #$FF
C3F1 D7 D0 staB L00D0
C3F3 BD ED F6 call LEDF6
C3F6 7E C3 7B jmp LC37B
;
;
C3F9 DIAG_jump_vectors:
C3F9 dw DIAG_test_fuel_pump
C3FB LC3FB: dw DIAG_test_injectors
C3FD LC3FD: dw DIAG_test_coil
C3FF LC3FF: dw DIAG_test_vae
C401 LC401: dw DIAG_test_overboost
;

Once you have entered the 5 comments, save and close the commented disassembly file and try running the dasm.bat file again.
Now when you look at the log file you should see that 5 comments were parsed and subsequently added.

This process continues until you understand the sections of code you are interested in (or all of it).

Have fun !

You might also like