Lecture Notes: Debugging with Memory Dumps, Registers, and Instruction Tracing
Floating Point Registers and Why They’re Not the Focus
- There are four floating point registers (FPRs).
- In this course we don’t deal with floating point numbers because it’s a bit too complex for the current scope, though the textbook has good chapters on it.
Dump and Display to Understand Program State
- The dump includes several pieces of state:
- The location counter for the current line of the dump is shown at address initially; this is the line-by-line memory dump.
- A dump automatically showing all the storage your program accesses.
- Below the register contents, you’ll see a dump of the register contents, and below that, a dump of the floating point register contents, captured at the moment of the dump.
- The purpose of the dump is to help you determine what went wrong and to diagnose potential logic errors when the program isn’t behaving as expected.
- If you force NAV (or similar actions), the dump can help you see what the system is doing and where a logic error may be occurring (e.g., a register holding an unexpected value, or a value not located where you expect).
Types of Errors: Three Levels
- There are three types of errors often discussed:
- Type 1: Compilation/Syntax Errors
- These are syntax errors reported by the compiler. Once resolved, you can run the program.
- Type 2: Runtime/Execution Errors (soft crashes)
- If the program crashes at run time, this is a runtime error that needs fixing.
- Type 3: Logical/Hard-to-Fix Errors
- The hardest to fix; for example, COBOL programs under certain parameter configurations. Your knowledge of assembly language and ABN (assembler) concepts can help debug COBOL.
- There are commercial debugging environments that are very feature-rich, but knowing how to read a dump lets you locate issues quickly without expensive tools.
- A COBOL program may involve many assembler-level packets; even a single COBOL verb can correspond to dozens of assembler bytes, illustrating why good debugging helps.
Storage Dump Layout and How to Read It
- The dump view is structured to make it easier to read storage:
- The dump lines show 32 bytes per line.
- Each line contains eight 4-byte groups (referred to in the talk as “forwards” across the line), totaling 32 bytes per line: there are bytes per line.
- If a line starts at address , the next line starts at address .
- Forward addresses/line boundaries:
- The first line starts at address .
- The next line begins at address , then , etc. (i.e., each line starts at multiples of : 0, 32, 64,
ext{…}).
- The addresses shown are forward-boundary addresses in the dump.
- Within the line, you can locate individual bytes by offset from the line start: bytes 0–31 correspond to the first line, 32–63 to the next line, and so on.
- A full word in the dump is typically 4 bytes (one 32-bit quantity).
- Example interpretation:
- The line shows the first byte at address , the line after at address , etc.
- A value at a given position (e.g., a 4-byte sequence) corresponds to a full word, which you can compare against your expectations.
- A common mental model: a line shows a base address and 32 bytes of data; the next line shows the next 32 bytes, and so on.
Layout Details and What to Look For
- The dump includes several key elements:
- The PSW (Program Status Word) snapshot for the line shown.
- The contents of the general purpose registers (GPRs).
- The contents of the four floating point registers (FPRs).
- The program storage area (memory) that your program accessed.
- If something seems off, the dump can tell you:
- Which register contains an unexpected value
- Whether a value is present at an expected address
- Whether a particular instruction was loaded correctly into a register or memory
- The dump often shows a readable ASCII interpretation on the right side:
- If a byte value corresponds to a printable character, it may show an ASCII character; for example, the digit '5' might appear as a character '5' in that ASCII pane.
- The right-hand side area may include an asterisk or dots. An asterisk indicates a noteworthy byte (e.g., a byte that has a specific property or was touched). If nothing more is present there, you would expect a column of dots representing untouched memory.
- If personal data (e.g., a customer’s name) appears in storage, you’ll see that in the ASCII view, which has privacy and ethical implications to be mindful of when sharing dumps.
Decoding a Line: Practical Clues in the Dump
An example of a line showing eight 4-byte fields (32 bytes total) across the line:
- The line is laid out left-to-right with 32 bytes per line, and lines progress to the right as you move through memory.
The left side shows addresses (e.g., 0, 32, 64,
), and the right side shows the corresponding data bytes.
You may see a sequence of bytes such as 0, 4, c, 1, 0, 1, 4, 1, 8, 1, c, … indicating the raw byte values in hex. Each 4-byte group forms a full word.
The digits and letters shown in hex map to the actual byte values in memory; the ASCII view converts those values to readable characters where possible.
If a line contains the sequence of 8 four-byte words (total 32 bytes), then the next line starts at the address that is + from the starting address of the previous line.
The dump may indicate an instruction fetch and its bytes; for example, two bytes showing the load instruction, followed by other bytes that form the next instruction, with the next instruction starting at an offset (e.g., 6) within the dump segment if a previous instruction spans bytes 0–3 and the next starts at 6 due to instruction encoding.
For example, if a bad instruction begins at the first two bytes, the next instruction could start at an offset (e.g., at offset 6) depending on encoding, which you can deduce by examining the dump.
Specific Elements You’ll See in the Dump
- The SOC (system/exception) codes in the dump, such as SOC 1 or SOC 7, which are traces of exceptions or events:
- SOC 1 is a specific dated exception trace.
- SOC 7 is another trace that may appear as part of a multi-instruction trace; it can show previous instructions that led to the outcome.
- The append (or appendage) area shows the instruction pointer trace and a short history of the last N instructions (a trace of the previous 10 instructions is typical in some environments, including the one described).
- In the example, the dump shows two lines because only one instruction was present, but the principle remains: the trace points to the instruction that caused the event.
- The bytes at the start of the line can reveal the bad instruction; for example, the two bytes at the start may encode a bad load instruction, with subsequent bytes forming the rest of the instruction or a following instruction.
- The value 0x20 is used to initialize a particular field in the dump (e.g., zeroed or initialized value) and the program’s end may be indicated by a 4-byte full word initialized to a specific value (e.g., 0x… which marks the end of the program). An empty portion of the dump should not exist in the assist environment; untouched registers are filled with 0xF4, and a loaded register may show a different value (e.g., register 4 showing 13) after loading from the full word.
- The right-hand side shows asterisks and dots to indicate changes or lack thereof across the dump lines; asterisks mark noteworthy bytes, and dots indicate no data change or unreadable characters beyond ASCII interpretation.
Practical Example: Assignment Five and a Register Context
- Assignment Five will provide you with machine code for a program and the hex machine code itself, along with two different register contexts.
- You will use the compare register instruction, abbreviated CR, to compare register contents:
- The mnemonic for the compare-register instruction is CR.
- You will compare the contents of registers positionally to determine equality or to drive control flow.
- Each position in the compare corresponds to a specific pair of registers or data elements being compared; understanding how CR operates helps you debug by checking if the expected values are present in the expected locations.
Practical Implications and Takeaways
- Reading a dump is a foundational debugging skill: it lets you verify the program state (PSW, GPRs, FPRs, and memory) at the exact moment of failure or a key event.
- Even when sophisticated debugging environments exist, the ability to interpret a dump quickly can save time and uncover subtle bugs (e.g., a wrong value in a register, a misaligned memory address, or an unexpected instruction).
- Understanding storage layout (32-byte lines, eight 4-byte words per line, and forward address boundaries) is essential for locating variables, constants, and control data in memory.
- Be mindful of privacy and ethical concerns when dumps contain real user or customer data; ensure appropriate handling in class exercises and disclosures.
- The three levels of errors provide a framework for troubleshooting: fix syntax first, then runtime crashes, and finally logic errors that require deeper analysis of the program’s flow and memory state.
Quick Reference: Key Terms and Concepts
- Floating point registers: Four FPRs
- Location counter: The memory address pointer at the start of a dump line
- Dump: Snapshot of PSW, GPRs, FPRs, and program storage
- PSW: Program Status Word
- GPRs: General Purpose Registers
- FPRs: Floating Point Registers
- Storage layout: 32-byte lines, eight 4-byte words per line
- Forward addresses: Line starting addresses increase by bytes
- ASCII dump: Right-hand interpretation of bytes as characters when printable
- Asterisk in dump: Noteworthy or changed bytes
- SOC codes: Trace/exception indicators in dump (e.g., SOC 1, SOC 7)
- CR: Compare Register instruction
- Assignment five context: Hex machine code, two register contexts, and use of CR for debugging