Thursday, 1 May 2008

Assembler: using debug.exe to write DOS programs


Windows (XP) still comes with Debug.

0C8A:0100 mov ax,0200
0C8A:0103 mov dx,0041
0C8A:0106 int 21
0C8A:0108 int 20
-h 010A 0100
020A  000A
CX 0000
Writing 0000A bytes


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).

      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
   AH = 02h
   DL = char value

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

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


  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

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

  2. working example:
    db 'blahblah$'
    mov ah, 09
    int 21
    int 20
    -h 0100 0117
    (value u got with the "h" single-letter command)

  3. How to use mov 41h?


All comments are moderated