If you want to write assembly code, you need an environment to do that. There are lots of ways. The most primitive way must be Debug (debug.com) which you can find in any machine that includes MS-DOS. It can be very hard, depressing and time consuming to write in Debug . But it has some very satisfying sides like bringing you closer to the processor and also we got to see what the hell is going around debug because it exists and stays next to us.
Now, we are going to see how to use debug. Concentrate on it !
This is where we command debug. We write letters like a,n,l,d,t,g to give directions to debug to write program, to save, to load, etc. Let's talk about them respectively.
To start writing the code, we write ' a ' meaning ' assemble ', and press enter.
After finishing the line, we press enter two times and get the following:
To run the program, we write ' g ', which means ' go ', and press enter. The program starts to run and ends with the first break. (Use int 3 (break) or int 20 (return to DOS) instructions otherwise the computer is locked. If you want to save the program int 3 will not be enough not to lock the computer. Use Int 20 there. And you have to be careful about DS. DS should have the previous value after your program finishes. So you should use 'push ds' and 'pop ds'.)
To return to DOS from debug environment, write 'q' and quit.
Now, let's write a simple program - a program that adds two numbers. We are going to use AX and BX registers and the sum will be in AX. (AX=AX+BX)
Let me explain what is done here. I use '«' instead of saying press enter.
- C:\> debug «
-a « ; start to write code
mov ax,03 « ; pass AX 03, AX will be 03
mov bx,04 « ; pass BX 03, AX will be 04
add ax,bx « ; add AX with BX, the sum is in AX
int 3 « ; break
-g « ;run, that is, go to 0100 because IP is 0100 (IP=Instruction Pointer, the code at the address it shows is executed)
And the result is directly shown by debug just after 'g « ". So, we see the sum ,07, is in AX.
We can use 't' to trace and see step by step what the program does, that is, we can follow the value of registers. But just at this point, the usage of trace will not work. In fact, even 'g' will not run the program. That is just because of the value of IP. Look at it. It is 0108. But our program starts with 0100. So the value of IP should be changed into 0100. We do that using 'r'. If you write 'r' and press enter, you see the value of registers. If you want to pass a value to a register, you write ' r ax' or 'r bx' or 'r ip' or whatever and press enter.
Look at the new value of IP now. So, if you say go, the processor executes what is in 0100, which is mov ax,03 here, and increases the value of IP until a break occurs.
How to Save Program
So, until now, we used a, g, t, r, q instructions and wrote a simple program. Now, let's see how to save a program. You are going to see how strange and how different it is from any ordinary saving task in other programs.
Now suppose that we are here. There are three stages to save this program.
- Write 'n' and the name of the program like -n first.com
Now the interesting point. We should specify how many bytes will be saved. So, we have to pass a value to CX register.
- Write r cx and press enter. And enter the number of bytes you want to save. Practically, write the difference between where your program starts and where it ends. In this example, 0109-0100=9 bytes. More practically, look at the last address and take its low byte. It will be sufficient if the high byte of the address is 01.
- Finally write 'w' and the program will be saved. Now, let's see it.
Here the order of passing a value to CX register and naming the program is not important. In fact sometimes you don't even need to specify the value of CX. Because you know it has the convenient value. For example, if you return to DOS and again enter debug the value of CX will not be changed. I am doing to show you this after speaking about how to load a program. But there is one more thing we should be aware of. The value of IP. It should be 0100 here because it is the start point of the saving process. For example, if we tried to save this program after running it, the value of IP would be 0109 and we would get a message like 'writing 40009 bytes', maybe we would think we saved it but we wouldn't be able to load the program later.
You see how many bytes are saved. Let's try to load it.
It didn't work.
Here I made a mistake. I tried to explain something to you in terms of things I didn't mention before. Before telling you how to load a program, I used it to express something. Sorry about that. I don't think here it will be a big trouble. Because it is a simple to figure out stage. But in classes there can be lots of those kind of problems, so be careful. Let's turn to our subject now.
How to Load a Program
There are two ways. One is, as we see above, writing debug and the name of the program and press enter. Then write 'u' (unassemble) to see the code.
You see, with ' u ' debug shows us the code with op-codes. So for example, we can easily say that B8 is the operation code of mov ax,...
The second way of loading a program is using 'l' (load). Let's see how.
We write 'n' and the name of the file which will be loaded. Then we write just ' l '. And the program is loaded. If it is wanted to see the code, u can be used.
So, I want to finish this talking about an interesting point. Suppose that we want to replace the line with ' ADD AX,BX' with 'SUB AX,BX'. You see the address of that line. It is 0106.
Here to be able to show you clearly I quit debug and again enter. Then I loaded first.com. But I didn't use u (unassemble) not to turn environment into a mess. I know that just at this point in the line 106 there is ADD AX,BX. So, to replace it, we write a 106 and press enter. Then line 106 comes in front of us empty. We write what we planned to write and press enter two times. And that is it. It's changed.
Here there is another interesting point that I have mentioned before about the situation of CX. You see here that I didn't pass a value to CX. But writing was completed successfully because I knew the value of CX. It was 9 which I specified when loading the program and which never changed during all the processes done until now. I surprised a lot of my friends with this. :)
- 30th June, 2009: Initial post