Wednesday, February 9, 2011

What can cause MASM to display "junk"?

I have some code which is supposed to display a short message. Here's the pertinent code:

DATA    SEGMENT 'DATA'
MSG DB 0AH, 0DH, 'Hello, Adam', '$'
CHAR    DB 00H
DATA ENDS

CODE    SEGMENT 'CODE'
PRINT_MSG:
    MOV AH, 09H ;Command to print string of characters
    MOV DX, OFFSET MSG ;Mov address of message into DX
    INT 21H  ;DOS Interrupt
    JMP WAITING ;Loop back to waiting state
CODE ENDS

And the output is:

E:\ece323\software\lab2>MAIN.EXE
?F ^?¶ ? N?   ?               -!-

Hello, Adam-

What is going on here?

  • My guess is that your DS does not point to your data-segment.

    Int21 Function 0x09 takes the string from DS:DX.

    Remember that DX is only a 16 bit register. To access data outside the 16 bit range you have to use segment registers. These are called DS and ES for data, CS for code and SS for the stack (there are FS and GS on i386 as well).

    The exact address you load from is given by 16 * segment_register + offset_register. Int21 cannot guess where your DS is, so you have to load it prior to call the interrupt.

    I guess you have never initialized your DS register, so it most likely points to the code, not the data-segment.

    Try to replace your

      MOV DX, offset MSG
    

    by:

      LDS DX, MSG  ; Check that, it's been ages since I've written 16 bit code.
    

    Unfortunatley it's been years since I've last played with 16 bit assembler, so I can't check it, but LDS should do the trick.

    You may also load DS indirectly at your program startup by something like this:

      MOV AX, SEG DATA  ; check that - can be SEGMENT or so as well.
      MOV DS, AX
    
  • My guess is that you are probably not running in "Real" mode, which is needed for MSDOS programs in general (and Int 21h interrupts in specific) to work.

    Windows has been running exclusively in "Protected" mode since Windows 95; The Command Prompt has been in Protected mode since, I think, Windows 2000.

    You may want to try create a shortcut do you EXE, and then setting the Compatibility options in the shortcut.

    Nils Pipenbrinck : Windows Command prompt will emulate all that stuff for you and lets you call int21 just fine. Also all DOS programs (.EXE and .COM) start in 16 bit mode. There is no need to set the compatibility options.
  • Try the following change:

    DATA    SEGMENT 'DATA'
    ERROR_MSG DB 'DS:DX is wrong'
    MSG DB  0AH, 0DH, 'Hello, Adam', '$'
    CHAR    DB      00H
    DATA ENDS
    

    If the error-message displays then DS:DX is wrong, so either DS doesn't point to the DATA segment, or 'OFFSET MSG' is wrong for some reason...my asm is rusty but try ADDR instead of OFFSET (?)

    If the error-message doesn't display, the problem happened before execution reached PRINT_MSG.

  • Nils is right, DS register need to be set in order to use this function of int 21. Try the second part with EAX transition first, it should work for sure.

    And there's no need in 0 char after the string. 9-th function doesn't work with null terminated strings, this '$' char works instead of 0.

    From akalenuk

0 comments:

Post a Comment