IBM's thing has always been to sell the idea of not having to "reinvent the wheel" when they come out with a new more powerful system rather the new system can "emulate" the customer's old hardware. Could this be what the FE was referring to?
Single Stepping Mechanism allows to execute only one instruction currently being pointed by Program Counter and then the Monitor Progam allows you to chcek/change the register contents. This is a great way to correct a program that has logical errors which is really difficult to detect by reading the code.
8086 MPU has hardware suppot for executing one onstruction at a time through the careful implemetation of the Trap Flag (T) of the Flag Register.
89S52 has also hadware support for single stepping.
8085 does not have hardware suppot for single stepping; however, it can be implemented by couning the number of bytes in an instruction, which is either 1 or 2 or 3. From the 8-bit opcode, one can easily count the length (number of bytes) of the current instruction to be single stepped.
I was debugging FORTH words, FORTH compiles everything into bytecode, which in final instance run the basic words (where the code is in FLASH already). The step from one word to another is done by NEXT code, so I "hacked" this.
So say I typed this on the keyboard:
It was byte-compiled into something like this (but I have there 24bits CELLs, so everything is 3bytes wide, except exeptions. Note, that CELL used as pointer may address 256kB FLASH $0000..$3FFFF, 64kB RAM $800000..$80FFFF and other chips, like 128kB SharedRAM $90000..&AFFFF and so on):
1CELL Pointer_to_prev_head
1byte flags // if this word is visible, immediate etc...
1byte len_of_name // 5
5byte name // ascii
1CELL code_word // address of f_docol code in FLASH - it 'execute' the rest of word
--- end of header, code follows, each 1CELL (3bytes) long
w_zero // put 0 on stack, 0 is used so often, I made word for it, as it is faster then decode number - server as counter
// BEGIN si used in compilation, not in runtime, so no code
w_dup // duplicate top of stack (get byte to print now)
w_emit // prints the byte as character ~ Serial.write(b_byte);
w_one_plus // again special word, it is just 5 asm instructions, but say, I implemented it in FORTH like : 1+ 1 + ; - increase counter
w_dup // need copy counter for comparation
w_lit 0x000100 // literal puts next cell to stack
w_minus // sub $100 as max_count from counter
w_is_zero // return TRUE if zero (so 255 chars was emited), FALSE otherwise
w_0branch -9*3 // (from UNTIL) if FALSE jump to BEGIN
w_drop // destroy counter
w_exit // return to caling word
When later is ascii called, the NEXT executes ascii so its code_word, the f_docol standard code is jumped to, it push return address to return stack, set IP to first cell and jumps to NEXT
(NEXT is hacked, so it prints logs, or interact with user or what. No write to FLASH/RAM needed.)
NEXT increase IP and executes w_zero its codeword is in FLASH and puts zero to stack, then jumps to NEXT. (NEXT is hacked, so ..)
NEXT increase IP and executes w_dup its codeword is in FLASH and duplicate TOS, then jumps to NEXT. (NEXT is hacked, so ..)
NEXT increase IP and executes w_emit its codeword is in FLASH and pop TOS and send it to standard output, then jumps to NEXT. (NEXT is hacked, so ..)
// 1+ is composite word, defined in FORTH, placed in FLASH in compilation as many other standard words, we will call it:
NEXT increase IP and executes w_one_plus its code_word, the f_docol standard code is jumped to, it push return address to return stack, set IP to first cell and jumps to NEXT. (NEXT is hacked, so ..)
NEXT increase IP and executes w_one its codeword is in FLASH and puts one to stack, then jumps to NEXT. (NEXT is hacked, so ..)
NEXT increase IP and executes w_plus its codeword is in FLASH and pops 2 cells, add them together, then push the result*, then jumps to NEXT. (NEXT is hacked, so ..)
NEXT increase IP and executes w_exit its codeword is in FLASH and pop return address into IP, then jumps to NEXT. (NEXT is hacked, so ..)
// so we are back just after 1+ call
NEXT increase IP and executes w_dup its codeword is in FLASH and duplicate TOS, then jumps to NEXT. (NEXT is hacked, so ..)
NEXT increase IP and executes w_lit its codeword is in FLASH, this read next cell ($100), push it on stack, increase IP to point after the used next cell, then jumps to NEXT. (NEXT is hacked, so ..)
NEXT increase IP and executes w_minus its codeword is in FLASH and pops 2 cells, sub them together, then push the result**, then jumps to NEXT. (NEXT is hacked, so ..)
..... and so on and so on - before each word is executed NEXT, and NEXT is hacked, so ...
Basically it behaves like if you placed breakpoint before every instruction, but it does not eat space.
*) simplification, it is asm word, which pops second cell from stack and adds it to TOS, which is faster and shorter, but does the same result
**) again simplification
Okay, I see. I thought you had figured out how to single step the machine instructions without have to erase and reprogram the flash like the debug capability does on the 328. That results in significant wear on the flash and Atmel/Microchip warn against shipping any product that has been used that way.
for that I used simavr+gdb or Disassembler for ATmega2560 (Arduino Mega R3) - both runs on PC and use its RAM, so no stress with breakpoints wearing something.
For most of my purposes it was sufficient, so I debuged most of my SW there and for real HW I started with system, which mainly worked, except maybe some time critical devices.
Then I used the "print" approach, where some checkpoints did something visible - send string to Serial, ligh LED, set colors on line of RGB LEDs, wrote something directly to the screem etc.etc.
But the FORTH engine have in RAM just the pointers (and headers) and when I have debuged the basic asm words (which is relatively easy, they are just few instructoins long), then for me the pointer was really atomic access to FORTH engine, nothing fine graded was not there.
Nowadays for $16 you can buy the Microchip XMIN board for the 328P and debug right on the hardware. They also use some kind of trick to limit wearing out the flash.
Most of the debuging was atmega2560 specific, like coordination of PG3 (A16) with PJ+PK(A0..15) and PD7 (/Read), PE5(/Write), PG5 (Select) for accessing external SharedRAM.
The simple words usually worked on first try, or it was easy to see, what is wrong (2push instead one, 2pop instead 1, or vice versa, wrong order of substraction and such - working code, bad data result)
In the 8086, the single-step mechanism automatically saves the address of the next instruction to be sngle stepped on the stack. When the STEP key is pressed, the monitor program retrieves the return address from the stack and loads it into the CS:IP registers (the Program Counter), allowing execution to continue one instruction at a time.
In the case of the ATmega328P, however, the debugger must determine the length of the current instruction (which is not a trivial task --I tried to do it a few years ago but could not complete it). It then inserts a breakpoint instruction at the address of the next instruction to be executed. This requires erasing and reprogramming the Flash memory, which contributes to Flash wear over time.
I sometimes wonder why the AVR development team could not implement a hardware-assisted single-step mechanism similar to that of the 8086, which would have avoided the need to erase and reprogram Flash memory during debugging.
Interested readers my read the following write-up to see how the author of this post has implemented S/S in his 8086 Trainer taking the help of Trap (T) Flag bit of 8086.
8086 Instruction to manipulate T-bit:
i. There is no direct instruction to set/reset the T-bit.
ii. The T-bit can be set/reset by storing the FR into the stack
Example:
pushf ; FR (16-bit ) is in stack (Fig-2.36)
mov bp, sp
or ss:[bp+00h], 0100h ; 0000 0001 0000 0000; T-bit=LH
poph ; now T-bit of FR is LH
(a) Putting LH at T-bit (b) Trick to Execute One Instruction
Figure-2.36: Explaining Trick of Putting LH at T-bit and Executing One Instruction
Use of T-Bit:
Let us see the use of T-bit in the execution of only one instruction of the following sample program.
The Sample Program:
02000 (0000:2000) - B0 12 : mov al, 12h
02002 (0000:2002) - BA 00 36 : mov dx, 3600h
02005 (0000:2005) -
We wish to execute the 1st instruction only. After the execution of the 1st instruction, the 2nd instruction would be ready for execution. After that, the next instruction would be executed and so on until all the instructions are executed one-by-one.
Procedures:
1. Push the FR into stack of Fig-2.36:
pushf ;[Fig-2.36 (a)]
2. Push Segment part of the current instruction``on stack :
mov ax, 0000h
push ax ;[Fig-2.36 (b)]
3. Push Offset part of the current instruction onto stack
mov ax, 2000h push ax ;[Fig-2.36 (c)]
4. Put LH at T-bit of FR, which is on stack of Fig-2.36: mov bp, sp
or [bp+04h], 0100h
5. To execute the 1st instruction, its address 0000:2000 must ‘some how’ be placed in the CS- and IP-register of the 8086. This can easily be done by putting them on the stack in the way that we have done above.
6. Now execute the instruction iret (not the ret). The IP- , CS-, and the FR-registers would be replaced by the values that are in the stack of Fig-2.36(b).
During the execution of the iret instruction, the 8086 doesn’t sample the flag bits of the FR. Therefore, the CPU will not be interrupted and it will proceed to the execution of the instruction pointed by cs:[ip], which is our 1st instruction in the program at location 02000 of the above sample program.
While executing the current instruction at address 0000:2000, the CPU samples the FR-register and finds that the T-bit is set. The CPU is immediately interrupted and prepares to jump to an Interrupt Sub Routine due to Trap Interrupt (ISRT).
Before jumping to the ISRT, the CPU
a. Finishes the instruction pointed by cs:[ip], which is our 1st program at location 02000h,
b. Saves the FR onto the stack and resets the T-bit
c. The 20-bit address of the next instruction (0000:2002) is saved in the stack.
Now, we have seen that only one instruction of the program has been executed and the 2nd instruction is ready for execution. We may now follow steps-4, 6 to single-step the 2nd instruction. All the remaining instructions of the program could be easily single-stepped (S/S) in this manner. The summary procedure is:
Main Line Program: Interrupt Subroutine for Trap:
ML1: FR --> Stack ISRTL1: Display register contents
ML2: 1st Instruction address --> Stack ISRTL2: If (Home key not pressed)
goto ISRTL1
ML3: Put LH at T-bit of Stack
ML4: if (s/s key not pressed) ISRTL3: goto ML3 maintaining stack
Goto ML4
ML5: execute iret instruction artificially
How would they have got the AVR to execute an instruction out of RAM?
Was AVR there at the arrival time of AVR?
Why are we still discussing RAM?
A computer DOES NOT need RAM.
As long as it is somehow programmable...
I don't know what that means.
Sorry!
The line would have been the following: (sign is no good at only 71+)
Was AVR there at the arrival time of AVR 8086?
I don't know off hand but it's irrelevant as to why Atmel chose to do it the way they did. Only until the modern day development boards is a separate processor used to emulate the e.g. 328P instruction set, therefore taking most of the strain off the flash.
I think, that one of the resons was, that AVR was build to be produced in mass and programmed in mass, where some debugging was not expected on final product.
And engeneers in big company can use special SW debuggers and burn lot of chips before the milion peaces series start produce ![]()
It was not made to be playtool for beginers afraid of C++ (which is Arduino planned target), so it was not optimised for them.
Yes, it's very clever...
89S52 has also hadware support for single stepping.
Really? I don't see anything about ANY debugging support in the 89S52 (or other old 8051-like chips.)
Many of the early microprocessors had "hardware" single stepping, back to the "step" switch on the Altair 8800. Usually implemented by detecting CPU state via external pins and driving a HALT signal (not much use for SW debugging!)
I could swear that CP/M software debuggers on 8080 and z80 had single stepping, but on checking, I see no support anything like the x86 "trap" flag. I guess they did the instruction-size counting you mentioned, and inserted a RST instruction at the appropriate point(s) (easy if your program is in RAM.)
Since the AVR always executes exactly one instruction between interrupts, I suppose you can implement hardware-assisted single stepping using an unusued interrupt or pin-change interrupt.
Theoretically, the ATmega328p supports debugwire, which apparently supports a SINGLE hardware breakpoint. But the external debugging software doesn't use this for single-stepping (I suppose that single-stepping a conditional branch requires at least two HW breakpoints?)
The newer (UPDI) debugging has additinal breakpoint capabilities.
(I guess those all require external debugging equipment, so they may not meet the requirements we are talking about...)
Not necessary for the 8086-style implementation, which traps after every instruction regardless of where it was fetched from. I imagine this is a lot harder to implement in an architecture with only one cycle per instruction...
Was AVR there at the arrival time of 8086?
No. 8086 came out in 1978. The first AVRs were in 1996.
First (?) implementation of single-step support similar to the x86 was apparently the PDP11's "Trace trap."
Yeah, AVR was aimed explicitly at PICs and 8051s...
I suppose that it's also worth pointing out that by the time PICs and AVRs the market, PCs were common and a lot of debugging could be accomplished via simulation.
This is what I did several time on Motorola 68000 series. Useful when I could not get to the real machine which was in a Unisys check reader/sorter.
Yes, I realize that. I was trying to get @GolamMostafa to think about the architecture difference and consider that the 328P can't execute code out of its SRAM which is what would be necessary to prevent exceeding the flash writes limit since flash memory must be temporarily changed then restored in order to do debug.
89S52 has also hadware support for single stepping.
Really? I don't see anything about ANY debugging support in the 89S52 (or other old 8051-like chips.)
I had followed the Guide Lines of Fig-1 of he 8051 Architectue to implemement Single Stepping in my 8951/89S52 Trainer (Fig-2) developed in 1999:
Figure-1:
Figure-2:
I had followed the Guide Lines of Fig-1 of he 8051 Architectue to implemement Single Stepping in my 8951/89S52 Trainer (Fig-2) developed in 1999:
Ah - the same scheme I had suggested might work on AVR - using an continuous external interrupt.



