Thursday, 1 May 2008

Assembler: using debug.exe to write DOS programs

C:\WINDOWS\system32\debug.exe


Windows (XP) still comes with Debug.

C:\test>DEBUG
-a
0C8A:0100 mov ax,0200
0C8A:0103 mov dx,0041
0C8A:0106 int 21
0C8A:0108 int 20
0C8A:010A
-h 010A 0100
020A  000A
-n PCHAR.COM
-rcx
CX 0000
:000A
-w
Writing 0000A bytes
-q

C:\test>PCHAR.COM
A


The above is the console output for writing a 10 byte executable in assembly language. All the application does is print out the A character (ASCII value 41h, sort of - it is more likely to be Code Page 850 on a Western European PC).

Registers and Interrupts

API: Interrupt Services

The common registers (AX, BX, CD, DX) are 16bit. The processor might be 32bit or 64bit, but it will be emulating 16bit here. A register like AX can be considered as two bytes and documentation will often refer to its separate byte values, AH and AL (high and low).

AX
      AH       AL
00000010 00000000


Thus, a value of AH=02h and AL=00h can be expressed as AX=0200h.

INT 21h,2h
Description: outputs character to STDOUT
Inputs:
   AH = 02h
   DL = char value
Outputs:
   none

INT 20h
Description: program terminate (deprecated: use INT 21h,4Ch to terminate with return code)
Inputs:
   none
Outputs:
   none

Understanding the Console Output

C:\test>DEBUG start Debug
-a assemble; note that the default start address is 0100h
0C8A:0100 mov ax,0200 set the register AX with hexadecimal value 0200h; the interrupt sub-function in AH
0C8A:0103 mov dx,0041 set the register DX with the hex value 0041h; the character to be output in DL
0C8A:0106 int 21 call interrupt 21h; since the value 02h is in AH, this tells DOS to output a character
0C8A:0108 int 20 call interrupt 20h; this tells DOS to terminate the program
0C8A:010A press ENTER again to finish
-h 010A 0100 calculate the difference between the end address and the start address
020A  000A hexadecimal; the sum is 020Ah;the difference is 000Ah (10)
-n PCHAR.COM name the output file
-rcx register CX
CX 0000 the current value in register CX
:000A set the value of CX to the difference from above (000Ah)
-w write the file
Writing 0000A bytes the number of bytes written (10)
-q quit
C:\test>PCHAR.COM execute the resultant program
A

5 comments:

  1. How can i do that magic in NASM? I've tried everything with no success. My latest failure looks like this:

    org 0

    jmp start

    start:
    mov ax,0x0200
    mov dx,0x0041
    int 21
    int 20

    ReplyDelete
  2. working example:
    -a
    db 'blahblah$'
    mov ah, 09
    int 21
    int 20
    (space)
    -h 0100 0117
    -rcx
    (value u got with the "h" single-letter command)
    -n blah.com
    -q




    ReplyDelete
  3. How to use mov 41h?

    ReplyDelete

All comments are moderated