Prashant Pandey
Prashant Pandey

Reputation: 139

Problems with outputting newline characters to a file

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?

Upvotes: 3

Views: 472

Answers (1)

Michael Petch
Michael Petch

Reputation: 47633

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.

Upvotes: 5

Related Questions