Проблемы с выводом символов новой строки в файл

Я пишу программу DOS для создания файла и записи в него. Мне нужно записать данные в две разные строки. Вот мой код:

.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

Я использую MASM и DOSBOX. Проблема в том, что хотя программа печатает данные в двух разных строках, но перед второй строкой она также печатает некоторые странные символы, а затем печатает строку msg. Что не так с этой программой, и как я могу это исправить?


person Prashant Pandey    schedule 14.03.2016    source источник
comment
Кажется, что нужная строка имеет длину 28 байтов (десятичных), и вы запрашиваете запись 28h (40 десятичных) байтов с mov cx,28h. Может ты имел ввиду mov cx,28?   -  person Michael Petch    schedule 14.03.2016
comment
Моя плохая, я попробую.   -  person Prashant Pandey    schedule 14.03.2016
comment
Или, лучше, попросите ассемблер вычислить длину вашей строки, используя директиву msglength equ $-msg сразу после определения msg.   -  person Peter Cordes    schedule 14.03.2016
comment
Пока я набирал этот комментарий, Питер предложил нечто подобное. Вы можете заставить TASM вычислить длину строки за вас. Поместите msglen equ $-msg сразу после определения msg. Это вычислит размер (длину) msg, а затем вы можете использовать это значение, заменив mov cx, 28h на mov cx, msglen.   -  person Michael Petch    schedule 14.03.2016
comment
Еще одна особенность. Не похоже, что вы пишете символы новой строки в файл, но отображаете их на консоли (int 21h / ah = 2 выводится на стандартный вывод). Разве вы не должны записывать их в файл? Вы можете добавить новые строки к самому msg, используя что-то вроде msg db 'Prashant Pandey 2014A7PS100G', 13, 10   -  person Michael Petch    schedule 14.03.2016
comment
Я изменил 28h на 28, но теперь он печатает, не меняя строки. Он печатает строку дважды в одной строке (хотя он не печатает никаких нежелательных символов. Я думаю, что запись с 28 на 28h была проблемой).   -  person Prashant Pandey    schedule 14.03.2016
comment
@MichaelPetch Думаю, вы правы, я попробую, так как я не могу изменить ни одной строки в текстовом файле!   -  person Prashant Pandey    schedule 14.03.2016


Ответы (1)


Пара проблем в вашем коде. Ваша строка Prashant Pandey 2014A7PS100G состоит из 28 символов, однако при записи в файл вы указываете 28h (шестнадцатеричный) с инструкциями:

mov cx,28h

Я думаю, вы хотели использовать 28 десятичных знаков. Измените две строки, соответствующие приведенному выше, на

mov cx,28

Лучшее решение - попросить ассемблера вычислить длину за вас. Это можно сделать, создав константу, представляющую длину строки. Примером этого может быть написание этого сразу после определения msg:

MSGLEN equ $-msg

Итак, код будет выглядеть так:

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

$ является эквивалентом счетчика текущего местоположения. Сразу после того, как вы определите свою строку с помощью msg db, счетчик местоположения будет местоположением байта после последнего символа msg. Если вычесть из него адрес метки msg, вы получите длину строки. директива EQU эффективно создает постоянное значение, которое затем можно использовать в своем коде. Теперь вы можете использовать это так:

mov cx, MSGLEN

Теперь вы можете изменить строку msg, и вам не нужно беспокоиться о настройке размера вручную в коде.


Вторая проблема с вашим кодом заключается в том, что INT 21h / AH = 2h записывает в стандартные вывод (по умолчанию на консоль, если вы не перенаправляете его в другое место). Ваш код записывает символы новой строки в стандартный вывод вместо файла. Вы можете решить эту проблему, добавив новую строку к самому msg с помощью следующего кода:

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

В качестве альтернативы вы можете определить другую строку, содержащую 13,10, и использовать INT 21 / AH = 40h написать это так же, как вы это сделали для msg.

person Michael Petch    schedule 14.03.2016