Example 2 - Logging rl_wWhat if you can't find a similarly scaled measuring block or you want the raw value? In this case, there's a useful item in the Measuring Blocks called 'count'. It's simply (a*256 +b). So if you want to monitor a 16 bit value, you can use this assembly:
ROM:00442AF0 # ---------------------------------------------------------------------------
ROM:00442AF0 lhz r5, word_80299C
ROM:00442AF4 li r3, 0x36
ROM:00442AF8 srawi r4, r5, 8
ROM:00442AFC b sub_43930C
How did I derive this?
1) Look in the VCDS label file for anything called 'count'. For example:
085,4,Ignition Cycle,Counter
2) Find this entry in Table 1 (it's the 4th column - 0x05F0)
85 0x05ED 0x05EE 0x05EF 0x05F0
3) Look up this pointer (0x05F0) in Table 2. This gives me the flash memory location (0x0004 2AF0)
1520 0x05F0 0x0004 2AF0
4) We know that this assembly is just going to do this (a*256 +b) and send it out. So we'll be able to copy / paste the assembly at 0x0004 2AF0 into an unused part of the flash and modify it to read the ram location you are interested in.
In this example I'm going to log rl_w. I know it's a 16 bit value, but I can't really spot an existing similar measuring block that would already have the correct scaling. I'm going to output the raw value and process it later in Excel. This is straightforward since the scaling values are already present in WinOLS. Find a map with load (e.g. KFMIRL), right click to look at the properties and the scaling is right there (0.023438).
Just like in the first example, I've already looked up the ram location containing rl_w (0x7FEE58)
1) Find a free measuring block entry in Table 1. In this case, it looks like the whole of Measuring Block 8 is free, so we'll use the first entry in that.
8 0x0000 0x0000 0x0000 0x0000
2) Pick an unused pointer from Table 2. Unused is anything pointing to 0x0003 931C (the assembly at this location 0x0003 931C just sends 25 00 00 back to VCDS which means 'not used'). I've decide to use 11 since it is free in both Table 2 and also the FR. The FR steps right over it:
10 mshfm_w Luftmassenfluß SY_HFM>0 g/s 25 var 0 ... 364 g/s
13 XXXXXXXX Flagregister: Bits 16 FFh
11 0x000B 0x0003 931C
3) Find a free part of the flash. Free flash is normally FF FF FF FF FF FF FF FF ...In my flash, I've got unused space at 0x0007 C6A8. You could also check in IDA that there is no code or cross references in the area you think is free.
4) As explained before, I'll copy the assembly used for the 'count' function and modify it to use my ram location of rl_w (0x7FEE58)
ROM:00442AF0 # ---------------------------------------------------------------------------
ROM:00442AF0 lhz r5, word_80299C
ROM:00442AF4 li r3, 0x36
ROM:00442AF8 srawi r4, r5, 8
ROM:00442AFC b sub_43930C
Same as before, we'll need to modify the first and last lines.
First line: lhz r5, r5, word_80299C
Last line: b sub_43930C
lhzAll the lhz references are relative to the SDA (r13) address (0x7FFFF0). You either add an offset for ram entries bigger than 0x7FFFF0 or subtract an offset for ram entries smaller than 0x7FFFF0. This time we are subtracting so we'll need to calculate the two's complement value
rl_w 0x7FEE58
0x7FFFF0 - 0x1198 = 0x7FEE58
0x7FFFF0 + (-0x1198) = 0x7FEE58
0x7FFFF0 + 0xFFFFEE68 = 0x7FEE58
This works out to be
lhz r5, word_7FEE58
A0 AD EE 68
To get this opcode (A0 AD EE 68), look at the attached MPCxxx Instruction Set. Look up the LHZ instruction. The last 16 bits are the offset (0xFFFFEE68 for our variable)
bWe need to branch back to 43930C, since that's where the main program is. However, all the branch instructions are relevant to our
current address. Now that we've copied our code to 47C6B4, our
current address where we jump back from will be different and we need to recalculate the branch instruction accordingly.
Current address 0x47C6B4 and we need to jump back to 0x43930C.
We need to subtract an offset from our current address. Two complement binary maths actually means we don't subtract, instead we add a negative number...
0x47C6B4 - 0x433A8 = 0x43930C
0x47C6B4 + (-0x433A8) = 0x43930C
0x47C6B4 + 0xFFFBCC58= 0x43930C
This works out to be
b sub_43930C
4B FB CC 58
010010 111111101111001100010110 00
To get this opcode (4B FB CC 58), look at the attached MPCxxx Instruction Set. Look up the B instruction. Bit 6 - 29 the offset (0xFFFBCC58 for our variable)
Code we are going to copy:
Address Opcode00442AF0 A0 AD 29 AC
00442AF4 38 60 00 36
00442AF8 7C A4 46 70
00442AFC 4B FF 68 10
Paste the copied code at the free space and modify the first and last lines
Address Opcode0x0047C6A8
A0 AD 29 AC first line A0 AD EE 68
0x0047C6AC 38 60 00 36
0x0047C6B0 7C A4 46 70
0x0047C6B4
4B FF 68 10 last line 4B FB CC 58
Now we need to apply all this to our bin. We need to change it in several places
1) The modified entries in Table 1
original8 0x0000 0x0000 0x0000 0x0000
new8 0x000B 0x0000 0x0000 0x0000
0x00 at 0x1C58D8
0x0B at 0x1C58D9
2) The modified entries in Table 2
original11 0x000B 0x0003 931C
new11 0x000B 0x0007 C6A8
0x00 at 0xA7930
0x07 at 0xA7931
0xC6 at 0xA7932
0xA8 at 0xA7933
3) The extra hex code at the free space 0x0007 C6A8
originalFF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
newA0 AD EE 68 38 60 00 36 7C A4 46 70 4B FB CC 58
Then use a hex editor to paste this new hex into your bin.
I recommend that you load this patched binary in IDA again and disassemble. Double-check that the new assembly jumps back to the correct place. You must get the branch back to the main program correct! If you get it wrong and it jumps back randomly, some very funny things could happen.
You have been warnedHere I've loaded my modified bin back into IDA and disassembled again. Looks OK and the first and last lines are as I'd calculated.
ROM:0047C6A8 # ---------------------------------------------------------------------------
ROM:0047C6A8 lhz r5, word_7FEE58
ROM:0047C6AC li r3, 0x36
ROM:0047C6B0 srawi r4, r5, 8
ROM:0047C6B4 b sub_43930C
Again, the final thing we need to do is update the VCDS label file to add an entry for these new values. Open up the label file 06F-907-115-AXX.lbl and edit it to include the following.
008,1,Engine Load (rl_w)
Here's what it looks like when you read the Measuring Block. You can see the new values that you have created (Engine Load (rl_w)).
I've also included a log where you can see the standard Engine Load entry that is capped at 191.7%. Our new Engine Load entry that we have created now passes this ceiling and gives us the actual load (just remember to scale it by 0.023438).