Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Debugging: step over behavior #80

Closed
krangerich opened this issue Dec 28, 2023 · 4 comments
Closed

Debugging: step over behavior #80

krangerich opened this issue Dec 28, 2023 · 4 comments

Comments

@krangerich
Copy link

All the debugging capabilities are awesome!

But I have some additional suggestions regarding the "step over" button in the "CPU Control" window:

  • Currently, during "rep" instructions (rep movsw, ...), step over and step into behavior is the same. It would be very convenient, when "step over" would skip the loop and jump to the next instruction
  • Currently, if you "step over" a long call / int and a hardware int occurs, the debugger stops after the iret of the hardware interrupt (=somewhere randomly inside the long call / int function). I don't know if this is indented, but it would be more convenient, if it would reliably end up at the next instruction after the call / int you want to "step over"
@dbalsom
Copy link
Owner

dbalsom commented Dec 28, 2023

All the debugging capabilities are awesome!

Hi! Glad you find them useful.

  • Currently, during "rep" instructions (rep movsw, ...), step over and step into behavior is the same. It would be very convenient, when "step over" would skip the loop and jump to the next instruction

Agreed it would be nice to be able to skip reps and loops and such. Step over currently only has an effect on calls but if the current instruction is not a call I could just have it skip to the next decoded address.

  • Currently, if you "step over" a long call / int and a hardware int occurs, the debugger stops after the iret of the hardware interrupt (=somewhere randomly inside the long call / int function). I don't know if this is indented, but it would be more convenient, if it would reliably end up at the next instruction after the call / int you want to "step over"

So step over is a bit of a hack at the moment. The main issue is that there's no guarantee that you can step over anything. Internally I am saving the return address on a call, but we may not end up back at that address for various reasons, interrupts being one. So there is a timeout - if we don't return after a certain number of instructions I just break after the timeout elapses. This ends up plopping you in some random place. Without the timeout, you might just step over something and see the emulator just keep running again forever after. I wasn't sure which method is better in the end.

Do you know how other emulators/debuggers handle this?

@krangerich
Copy link
Author

I just checked debugging Java in IntelliJ IDEA as a random example. When you hit "step over" on a method and the method does not return (for example, there could just be an infinite loop), the program just keeps running and does not return to the debugger (unless another breakpoint is hit).

I think, this is simple and reasonable behavior for a debugger. If the function call / method call / .. never returns, you just have to start over again and use "step into" instead (or change breakpoints accordingly).
Basically you could act, as if there was a breakpoint on the following instruction.

@dbalsom
Copy link
Owner

dbalsom commented Apr 7, 2024

Hi @krangerich, I have implemented the new step-over behavior, on track for 0.2.1. I added step_over_target to REP string operations so they can be skipped.

It's a valid question as to why regular stepping doesn't work over REP string operations. MartyPC handles them a bit specially - on a real 8088 they are indeed a single atomic instruction that self-terminate on interrupts.

However this could mean that a single 'step' in the debugger could execute 1 million+ cycles. This robs us of the use of our debug windows to examine peripheral and video state during a string operation - if we step-per-iteration instead, we can literally watch the bytes get copied into memory, if we are doing a move into MMIO area we can see realtime device changes.

I think step-over REP is a good compromise.

There is another tweak I would like to do, and that is to keep the presently running string operation at the top of the debug window. Right now the only way to tell you are in one after the first iteration is to look into the cpu history, which get spammed with rep xxx entries.

There is another similar situation with HALT. Both of these technically advance CS:IP so the disassembler will skip them after they are first executed. Instead of feeding ip to the disassembler I think I will have an disassembly_ip() method that will rewind IP backwards for REP string and HLT instructions so they remain at the top of the disassembly view until they are resolved.

I'd like to add step-past as well; this would be handy for skipping past the end of various loops. I should probably disable it if the current instruction is an unconditional jump.

Step-out or step-return is also possible, but complicated by the ridiculous difficulty of tracking the 8088's call stack.

@krangerich
Copy link
Author

Hey, thanks, thats good to hear!
I'm not able to try it yet, because I'm currently busy on the hardware side (assembling a Xi8088, ...)

@dbalsom dbalsom closed this as completed Jun 18, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants