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 |
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 |
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 |
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
Post a Comment