Thanks to commenters I have already learned two useful things as a result of yesterday’s post, both things which I cannot fathom how I did not already know. But here’s something I learned for myself as a result of a comment made by Malcolm Groves at the Auckland Delphi 2010 launch day recently.
As mentioned in yesterdays post, a new feature in Delphi 2010 is the ability to drag and drop the execution point when stopped in debug mode.
However, Malcolm mentioned that this could be achieved – rather more awkwardly – in previous versions of Delphi via the CPU window, although the precise details escaped his memory at the time, other than that it involved modifying the contents of a particular register.
I found myself last night in exactly the situation I described in my speculative “when this might be useful” discussion of moving execution points. I happened to be in an older version of Delphi at the time and it was a relatively small project so a “halt, modify, recompile and retest” cycle wouldn’t have been too arduous, but I decided instead to reach for the CPU window to see if I couldn’t figure out how to achieve it and see just how awkward it might be.
It didn’t take long, and actually, it wasn’t too awkward at all.
Here’s the CPU view, with an additional bit of highlighting to draw attention to the useful areas (click to embiggen):
The two connected box highlights show that the EIP register contains the current execution point address. So this is the register that Malcolm was referring to.
Now, there are actually TWO ways we can use this information to change the execution point in older Delphi versions…
You can either position the highlight in the CPU disassembly view on the desired execution point and invoke the “New EIP” item on the disassembly context menu:
Or you can directly increment or decrement the EIP register using the register view context menu:
In this capture I’ve also highlighted the address of the next executable point corresponding to a line of source in my code – you will notice that the addresses in that list are non-contiguous, and when incrementing or decrementing the EIP value I think you need to be careful that you set the value to an address that corresponds to one of the addresses in this list.
When you increment/decrement the EIP register, the value is incremented as a simple value, without respect to this list of addresses. i.e. “Increment” add’s 1 (one) to the value, it doesn’t advance it to the “next valid address”.
I’m not sure what would happen if you tried to resume execution from an address that is not in that CPU disassembly list, but I’m pretty confident it wouldn’t be “good things”.
So grateful thanks to the commenters to my previous post and to Malcolm for furthering my awareness of things already at my disposal.
“what would happen if you tried to resume execution from an address that is not in that CPU disassembly list”. EIP simply tells the CPU where the next opcode is – and opcodes are just byte sequences. If you move it to the wrong place, the CPU will happily start to read some bytes and try to interpret them as instructions, and of course they will not be the rights sequence the compiler emitted – the result is unpredictable – it depends on what the altered sequence means to the CPU.
At least since Delphi 2002 the same function is available from the context menu of the editor window: It’s under debug -> set next statement
This functionality has also been available since Delphi 2006 from the context menu of the editor window:
debug -> set next statement
sorry about the first comment: Delphi 2002 did not exist, just a typo
At least as far back as D2007, and probably earlier, you could also right-click in the code view and say Debug -> Set Next Statement. No CPU view required.
Always great to see articles on debugger features.
As mentioned by Thomas and Mason, the ability to do this in the editor has been available since D2006. More info here: http://blogs.embarcadero.com/chrishesik/2007/04/30/34241
The ability to do this in the CPU view has been around since there has been a CPU view (I think it first appeared as an “official” feature in Delphi 3, though the CPU view was available in Delphi 2 by setting a hidden reg key).
@All – I didn’t mean to imply that any of this stuff was especially new in Delphi itself, but it was new(s) to *me*, and therefore might also be new(s) to others.
I generally don’t reach for the right-mouse menu when debugging or go hunting through menus on the off-chance that the debugging tools I need might be there. Consequently the existence of some of these tools had passed me by over the years.
Just as, for example, some people are astonished when they see me add a watch variable at the stroke of a key (Ctrl+F5), or search within a unit without invoking a modal “Find” dialog (Ctrl+E).
Things that have been there for years which I *have* learned and use regularly, but which somehow has passed *them* by.
Sigh, I guess you missed my sessions on Debugging with Delphi… 🙂
And those from Chris also.
But I agree with you, it is a very convenient and powerful feature all too often unknown from a lot of developers. So it’s good to raise awareness about it.
And the right-click “set Next…” made it even more convenient (also removing the need to pull out the CPU view which seems to scare so many)
Changing the instruction pointer is a very useful technique and something that was possible in the earliest versions of Turbo Debugger (TD, TD286 and TD32). I used to use this technique extensively in debugging and testing low-level code. Changing register values and IP/EIP is a quick way to replay segments of code with different inputs to “fix” problems or test conditional logic. Something akin to what can be done today in Java with on the fly class reloading, but much more dangerous and fun.