How to debug the BIN-Files

Reference picture of the post "How to debug the BIN-Files"

This post is the last of chapter VII. Here I write about how to debug a SOFTWARE.BIG program with DEBUG.EXE. This is the last piece of the puzzle to conclude the experimenting with the new tools. From now on, I will write code in NASM and debug it in DEBUG.EXE.

SOFTWARE.BIG is loaded at 0x0_7C00 with the entry point at 0x0_7C10 and from this point, the _general_reset routine sets all segments to be according the following schema: DS = ES = _justData, SS = _justStack and CS = _justCode. This means that I had to find a way to simulate the addresses in DEBUG.EXE to be somehow compatible with what the addresses are when SOFTWARE.BIG is loaded in real mode RAM. It took me a while and a couple of errors, but in the end, I found a very simple and elegant solution. First of all, I loaded the SOFTWARE.BIG in DEBUG.EXE at 0x7C00. In this way, the offset part of all addresses in DEBUG.EXE and in real mode RAM were aligned. After that, I assembled a small piece of code directly at address 0x100 that fixed the segments part of all remaining addresses. I wrote the code at address 0x100 because when DEBUG.EXE starts all segments are equal and the Instruction Pointer register (IP) points already at 0x100, so that writing directly at this address, reduced later on the effort for the setup. Once I had the code ready at address 0x100, I saved it into a binary file which I named: "STD-RUN.BIG" (the standard run for the SOFTWARE.BIG). Let me show you in the praxis how does it works, and for this case, I used the same SOFTWARE.BIG created with the file Learn NASM - 04.asm of the post "How to make a SOFTWARE.BIG with NASM" .

Fig. A - Loading of files in DEBUG.EXE
Fig. A - Loading of files in DEBUG.EXE

In Fig. A, you see that I loaded the SOFTWARE.BIG at 0x7C00 and the STD-RUN.BIG at address 0x100. As you can see, the decision to prepare STD-RUN.BIG at address 0x100, perfectly fits with the default initial setup of DEBUG.EXE and I can start immediately debugging with the command p. STD-RUN is the small piece of code in yellow that performs a small and crucial task at the same time. I observed that the definition of the segments in SOFTWARE.BIG is such that it assumes SOFTWARE.BIG being at 0x0000:7C00 and from this assumption it sets the new values for all the segment registers.
However, within DEBUG.EXE, SOFTWARE.BIG gets loaded at 0x????:7C00 (the four question marks stand for the unknown segment used when DEBUG.EXE is launched). So I observed that I could have injected this 0x???? value directly in the _general_reset routine of SOFTWARE.BIG as an offset to be added to the currently defined addresses for the segment registers. I knew that any of the segment registers contained the 0x???? that I was looking for when DEBUG.EXE was initially launched, so I copied this value in AX with the first instruction MOV AX, DS. Then I added the value of AX to the addresses defined for the segment registers directly in the middle of the instructions of the _general_reset procedure. To realize it, you should look at the lines 70, 73 and 77 of the file: Learn NASM - 04.lst and compare the addresses of this line with the green highlighted part on the right of Fig. A.
The very last instruction of STD-RUN is a jump to the beginning of SOFTWARE.BIG.

Fig. B - _general_reset opening routine of SOFTWARE.BIG
Fig. B - _general_reset opening routine of SOFTWARE.BIG

In Fig. B, you see the _general_reset opening routine of SOFTWARE.BIG (I highlighted it with green colour in the picture). When the _general_reset routine set the Stack Segment register (SS), DEBUG.EXE could not stop because the processor executed also the instruction immediately after it. This is a feature embedded in the CPU that allows a full setup of the stack in its segment and offset part all at once1. If you compare line 75 of the file Learn NASM - 04.lst with the addresses marked with red in Fig. B, you should be able to realize what I am writing about. At address 0x7C1B there is the instruction MOV SS, AX, at address 0x7C1D there is the instruction MOV SP, 0xFFFE and at address 0x7CFB the instruction STI but the CPU didn't stop after MOV SS, AX and processed also the instruction MOV SP, 0xFFFE before stopping again. It seems as if the instruction MOV SP, 0xFFFE didn't exist at all when analyzing the code within DEBUG.EXE.
The final part of the _general_reset set the Code Segment Register (CS) and the Instruction Pointer (IP) all together with a long jump.

Fig. C - Main program
Fig. C - Main program

In Fig. C, you see the testing of the main program (I highlighted it with blue colour). It is important to observe how all addresses are working in the DEBUG.EXE environment as if it were in the real-mode RAM the only difference being the different values for the segment registers.

This concludes the initial learning that I did with the new tool NASM. I am optimistic for the future and I think that NASM will enable me to continue my discovery of the deep-binary space in a better way than I did until now just with the sole use of DEBUG.EXE.

Comments