3

I am writing a DOS program to make a file and write into it. I have to write the data in two different lines. Here is my code:

.model tiny
.486
.data

fname db 'file5.txt',0
handle dw ?
msg db 'Prashant Pandey 2014A7PS100G'

.code
.startup
mov ah,3eh
mov bx,handle
int 21h

mov ah,3ch      ;the 4 lines from now open an new non-existing.3ch is used to open a new file
lea dx,fname
mov cl,2h
int 21h
mov handle,ax

mov ah,40h      ;these 4 lines write to the already opened file
mov bx,handle
mov cx,28h
lea dx,msg
int 21h

; new line
mov dx,13
mov ah,2
int 21h  
mov dx,10
mov ah,2
int 21h

mov ah,40h      ;these 4 lines write to the already opened file
mov bx,handle
mov cx,28h
lea dx,msg
int 21h 

mov ah,3eh
mov bx,handle
int 21h

.exit
end

I am using MASM and DOSBOX. The problem is although the program prints the data in two different lines, but before the 2nd line, it also prints some weird characters and then prints the string msg. What is wrong with this program, and how can I fix it?

Michael Petch
  • 46,082
  • 8
  • 107
  • 198
Prashant Pandey
  • 139
  • 1
  • 1
  • 13
  • 2
    Seems the string you want is 28 bytes (decimal) in length and you are requesting writing 28h (40 decimal) bytes with `mov cx,28h`. Maybe you meant `mov cx,28`? – Michael Petch Mar 14 '16 at 17:49
  • My bad.I'll try it out. – Prashant Pandey Mar 14 '16 at 17:53
  • 2
    Or better, get the assembler to calculate the length of your string, by using an `msglength equ $-msg` directive right after defining `msg`. – Peter Cordes Mar 14 '16 at 17:55
  • 1
    While I was typing this comment up Peter suggested something similar. You can get TASM to compute the string length for you. Place `msglen equ $-msg` right after the definition of `msg`. This will compute the size(length) of `msg`, and then you can utilize that value by replacing `mov cx, 28h` with `mov cx, msglen`. – Michael Petch Mar 14 '16 at 17:57
  • 1
    One other peculiarity. It doesn't appear you are writing the newlines into the file but are displaying them to the console (int 21h/ah=2 displays to standard output). Shouldn't you be writing them to the file? You could add newlines to the `msg` itself with something like `msg db 'Prashant Pandey 2014A7PS100G', 13, 10` – Michael Petch Mar 14 '16 at 18:00
  • I changed the 28h to 28.But now, it is printing not changing the lines.It is printing the string twice in the same line(It is not printing any unwanted characters though.I think the writing 28 to 28h was the problem). – Prashant Pandey Mar 14 '16 at 18:03
  • @MichaelPetch I think you're right.I'll try it out, since I can't change any lines in the text file! – Prashant Pandey Mar 14 '16 at 18:05

1 Answers1

5

A couple of issue in your code. Your string Prashant Pandey 2014A7PS100G is 28 characters long, however when writing to the file you specify 28h (hex) with the instructions:

mov cx,28h

I think you meant to use 28 decimal. Modify the two lines that match the above to

mov cx,28

A better solution is to get the assembler to compute the length for you. This can be done by creating a constant that represents the length of the string. An example of that would be to write this right after you define msg:

MSGLEN equ $-msg

So the code would look like:

msg db 'Prashant Pandey 2014A7PS100G'
MSGLEN equ $-msg

$ is the equivalent of the current location counter. Right after you define your string with msg db the location counter will be the location of the byte after the last character of msg. If you subtract the address of the label msg from that you will get the length of the string. the EQU directive effectively creates a constant value that you can then use in your code. Now you can use it like this:

mov cx, MSGLEN

Now you can modify the msg string and you don't have to worry about adjusting the size manually in your code.


The second issue with your code is that INT 21h/AH=2h writes to standard output (by default to the console if you don't redirect it elsewhere). Your code writes newlines to standard output instead of the file. You could resolve that by adding the newline to msg itself with code like:

msg db 'Prashant Pandey 2014A7PS100G',13,10
MSGLEN equ $-msg

Alternatively you could define another string that contains 13,10 in it and use INT 21/AH=40h to write that out just as you did for msg.

Michael Petch
  • 46,082
  • 8
  • 107
  • 198