Вывод символьной строки на экран - Assembler
Формулировка задачи:
Добрый вечер, реализовал программу, условие её такого что нужно из текстового файла прочитать 20 символов начиная с 10-байта в файле. Показать строчку на экране( что у меня не получается!!!!) и записать в новый файл по 4 символа в каждой строчке. Все условие программы у меня реализовано и работает прекрасно, но при выводе строк на экран выдает полнейшую чушь
Помогите разобраться
.386
stak segment
db 100 dup (0)
stak ends
;сегмент данных
dseg segment
txt1 db 'File Name Read: ',0dh,0ah,'$' ;текст перед запросом на имя файла
txt2 db 'Not Enter FileName!',0dh,0ah,'$' ;неуказано ничего в командной строке, например нажали Enter просто
txt3 db 'Open File Error!',0dh,0ah,'$' ;ошибка открытия файла
txt4 db 'Error Create File!',0dh,0ah,'$' ;ошибка создания файла
txt5 db 'File Name Write: ',0dh,0ah,'$' ;текст перед запросом на имя файла
txt6 db 'Stroka simvolov v file: ',0dh,0ah,'$' ;символы записываемые в файл
perehod db 0dh,0ah,'$' ;перевод строки и возврат коретки
buf_ db 0 ;буфер для чтения 4 байт
des1 dw ? ;хэндл файла который читаем
des2 dw ? ;хэндл файла который создается (tmp.tmp)
kol dw 0
stroch dw 0
;буфер для файл чтения
max db 254 ;максимально допустимая
len db 0 ;действительная длина данных
buf db 254 dup (0);буфер содержит ввод, заканчивающийся символом CR (ASCII 0dH)
;буфер для файл записи
max2 db 254 ;максимально допустимая
len2 db 0 ;действительная длина данных
buf2 db 254 dup (0);буфер содержит ввод, заканчивающийся символом CR (ASCII 0dH)
dseg ends
cseg segment
assume cs:cseg, ds:dseg, ss:stak
.386
start:
;настройка DS на сегмент данных
mov ax,dseg
mov ds,ax
;выводим приглашение
lea dx,txt1 ;текст txt1
call t1 ;процедура вывода текста
;запрос на ввод строки имя файла
mov ah,0ah
lea dx,max
int 21h
jc exit_1
cmp [len],0 ;если len = 0 значит не вводили в строке а нажали Enter
jne d1 ;если len <> 0 то d1
jmp exit_1 ;если 0 то мы ничего ни ввели в командной строке, выход
d1:
lea dx,perehod ;строка perehod
call t1 ;вывод текста
;что то ввели в строке, проверим мож файл?
;для это поместим в конец строки символ с кодом 0
lea si,buf ;в SI адрес буфера buf
xor bx,bx ;обнулим BX
mov bl,[len] ;длину строки LEN в BL
mov al,0 ;сделаем AL = 0
mov ds:[si+bx],al ;в строке которую мы ввели в конце есть символ 0Dh, адрес ее это буфер buf + дина LEN
;положим туда AL, а это 0, для открытия файла
;AL = режим открытия, AL = 0 чтобы открыть для чтения
mov ax,3d00h
lea dx,buf ;имя файлов, может включать и путь
int 21h
jnc create_file ;если не было ошибок при открытии
;если файла нет или ошибка была при открытии,выводим текст txt3
lea dx,txt3
call t1
jmp exit_dos ;на метку, выход в дос
;не было ошибок открытия, продолжаем
create_file:
;сохраним хэндл файла (описатель)
mov [des1],ax
;выводим приглашение
lea dx,txt5 ;текст txt5
call t1 ;процедура вывода текста
;опрос на ввода имени для записи
mov ah,0ah
lea dx,max2
int 21h
jnc create2 ;если были ошибки, то закроем файл 1 и выходим
cmp [len2],0 ;если len2 <> 0 то d1
je close2
create2:
lea dx,perehod ;строка perehod
call t1 ;вывод текста
;подготовка к созданию файла
;что то ввели в строке, проверим мож файл?
;для это поместим в конец строки символ с кодом 0
lea si,buf2 ;в SI адрес буфера buf2
xor bx,bx ;обнулим BX
mov bl,[len2] ;длину строки LEN в BL
mov al,0 ;сделаем AL = 0
mov ds:[si+bx],al ;в строке которую мы ввели в конце есть символ 0Dh, адрес ее это буфер buf + дина LEN
;положим туда AL, а это 0, для открытия файла
;создадим файл указанный в строке buf2
;Вход AH = 3cH
;DS:DX = адрес строки ASCIIZ с именем файла
;CX = атрибут файла
mov ah,3ch
mov cx,20h
lea dx,buf2
int 21h
jnc vse_ok ;не было ошибок при создании файла
;если ошибки при создании файл
lea dx,txt4
call t1
jmp close2 ;на метку закрытия первого файла
vse_ok:
;сохраним хэндл файла (описатель) (tmp.tmp)
mov [des2],ax
;организуем цикл для чтения и записи
lea dx,txt6
call t1
mov ah,42h
mov bx,[des1]
mov al,0
mov cx,0
mov dx,10
int 21h
cikl:
mov ah,3fh
mov bx,[des1]
lea dx,buf_
push dx
mov cx,1
int 21h
jc close1 ;если при чтении файла была ошибка то на метку close1
;при чтении в AX возсращается реальное считанное кол-во байт
;если 0 то закрываем файлы
cmp ax,0
je close1
;если встретили не конец строки
cmp [buf_],0Dh
jne write1
;если встретили конец строки
jmp close1
write1:
; Здесь вывод символа на экран но он не работает!!! точнее работает не коректно!
pop dx
push ax
mov ax,dx
add ax,41h
int 29h
pop ax
; запись в файл ... (работает)
mov cx,ax
mov ah,40h
mov bx,[des2]
lea dx,buf_
int 21h
mov bp,[kol]
cmp bp,19
jz short close1
inc bp
mov [kol],bp
mov bp,[stroch]
cmp bp,3
jz short otv
inc bp
mov [stroch],bp
;прыгаем на метку cikl
jmp cikl
otv:
mov ah,40h
mov bx,[des2]
lea dx,perehod
mov cx,2
int 21h
mov bp,0
mov [stroch],bp
jmp cikl
;закрываем файл (временный файл tmp.tmp)
close1:
;Вход AH = 3eH
;BX = описатель файла
mov ah,3eh
mov bx,[des2]
int 21h
;закрываем файл (который указан в командной строке)
close2:
;Вход AH = 3eH
;BX = описатель файла
mov ah,3eh
mov bx,[des1]
int 21h
jmp exit_dos ;на метку выход
exit_1:
lea dx,txt2 ;не ввели что либо в строке при опросе, выводим текст txt2
call t1
exit_dos: ;выход в дос
mov ax,4c00h
int 21h
t1 proc ;процедура вывода текста, в DX уже есть строка
mov ah,09h
int 21h
ret
t1 endp
cseg ends
end startРешение задачи: «Вывод символьной строки на экран»
textual
Листинг программы
model small stack 256 dataseg txt1 db 'File Name Read: ',0dh,0ah,'$' ;текст перед запросом на имя файла txt2 db 'Not Enter FileName!',0dh,0ah,'$' ;неуказано ничего в командной строке, например нажали Enter просто txt3 db 'Open File Error!',0dh,0ah,'$' ;ошибка открытия файла txt4 db 'Error Create File!',0dh,0ah,'$' ;ошибка создания файла txt5 db 'File Name Write: ',0dh,0ah,'$' ;текст перед запросом на имя файла txt6 db 'Stroka simvolov v file: ',0dh,0ah,'$' ;символы записываемые в файл perehod db 0dh,0ah,'$' ;перевод строки и возврат коретки buf_ db 0 ;буфер для чтения 4 байт des1 dw ? ;хэндл файла который читаем des2 dw ? ;хэндл файла который создается (tmp.tmp) kol dw 0 stroch dw 0 ;буфер для файл чтения max db 254 ;максимально допустимая len db 0 ;действительная длина данных buf db 254 dup (0);буфер содержит ввод, заканчивающийся символом CR (ASCII 0dH) ;буфер для файл записи max2 db 254 ;максимально допустимая len2 db 0 ;действительная длина данных buf2 db 254 dup (0);буфер содержит ввод, заканчивающийся символом CR (ASCII 0dH) codeseg .386 start: ;настройка DS на сегмент данных mov ax,@data mov ds,ax ;выводим приглашение lea dx,txt1 ;текст txt1 call t1 ;процедура вывода текста ;запрос на ввод строки имя файла mov ah,0ah lea dx,max int 21h jc exit_1 cmp [len],0 ;если len = 0 значит не вводили в строке а нажали Enter jne d1 ;если len <> 0 то d1 jmp exit_1 ;если 0 то мы ничего ни ввели в командной строке, выход d1: lea dx,perehod ;строка perehod call t1 ;вывод текста ;что то ввели в строке, проверим мож файл? ;для это поместим в конец строки символ с кодом 0 lea si,buf ;в SI адрес буфера buf xor bx,bx ;обнулим BX mov bl,[len] ;длину строки LEN в BL mov al,0 ;сделаем AL = 0 mov ds:[si+bx],al ;в строке которую мы ввели в конце есть символ 0Dh, адрес ее это буфер buf + дина LEN ;положим туда AL, а это 0, для открытия файла ;AL = режим открытия, AL = 0 чтобы открыть для чтения mov ax,3d00h lea dx,buf ;имя файлов, может включать и путь int 21h jnc create_file ;если не было ошибок при открытии ;если файла нет или ошибка была при открытии,выводим текст txt3 lea dx,txt3 call t1 jmp exit_dos ;на метку, выход в дос ;не было ошибок открытия, продолжаем create_file: ;сохраним хэндл файла (описатель) mov [des1],ax ;выводим приглашение lea dx,txt5 ;текст txt5 call t1 ;процедура вывода текста ;опрос на ввода имени для записи mov ah,0ah lea dx,max2 int 21h jnc create2 ;если были ошибки, то закроем файл 1 и выходим cmp [len2],0 ;если len2 <> 0 то d1 je close2 create2: lea dx,perehod ;строка perehod call t1 ;вывод текста ;подготовка к созданию файла ;что то ввели в строке, проверим мож файл? ;для это поместим в конец строки символ с кодом 0 lea si,buf2 ;в SI адрес буфера buf2 xor bx,bx ;обнулим BX mov bl,[len2] ;длину строки LEN в BL mov al,0 ;сделаем AL = 0 mov ds:[si+bx],al ;в строке которую мы ввели в конце есть символ 0Dh, адрес ее это буфер buf + дина LEN ;положим туда AL, а это 0, для открытия файла ;создадим файл указанный в строке buf2 ;Вход AH = 3cH ;DS:DX = адрес строки ASCIIZ с именем файла ;CX = атрибут файла mov ah,3ch mov cx,20h lea dx,buf2 int 21h jnc vse_ok ;не было ошибок при создании файла ;если ошибки при создании файл lea dx,txt4 call t1 jmp close2 ;на метку закрытия первого файла vse_ok: ;сохраним хэндл файла (описатель) (tmp.tmp) mov [des2],ax ;организуем цикл для чтения и записи lea dx,txt6 call t1 mov ah,42h mov bx,[des1] mov al,0 mov cx,0 mov dx,10 int 21h cikl: mov ah,3fh mov bx,[des1] lea dx,buf_ ; push dx mov cx,1 int 21h jc close1 ;если при чтении файла была ошибка то на метку close1 ;при чтении в AX возсращается реальное считанное кол-во байт ;если 0 то закрываем файлы cmp ax,0 je close1 ;если встретили не конец строки cmp [buf_],0Dh jne write1 ;если встретили конец строки jmp close1 write1: ; Здесь вывод символа на экран но он не работает!!! точнее работает не коректно! ;pop dx push ax ; mov ax,dx mov al,[buf_] ;add ax,41h int 29h pop ax ;запись в файл ... (работает) mov cx,ax mov ah,40h mov bx,[des2] lea dx,buf_ int 21h mov bp,[kol] cmp bp,19 jz short close1 inc bp mov [kol],bp mov bp,[stroch] cmp bp,3 jz short otv inc bp mov [stroch],bp ;прыгаем на метку cikl jmp cikl otv: mov ah,40h mov bx,[des2] lea dx,perehod mov cx,2 int 21h mov bp,0 mov [stroch],bp jmp cikl ;закрываем файл (временный файл tmp.tmp) close1: ;Вход AH = 3eH ;BX = описатель файла mov ah,3eh mov bx,[des2] int 21h ;закрываем файл (который указан в командной строке) close2: ;Вход AH = 3eH ;BX = описатель файла mov ah,3eh mov bx,[des1] int 21h jmp exit_dos ;на метку выход exit_1: lea dx,txt2 ;не ввели что либо в строке при опросе, выводим текст txt2 call t1 exit_dos: ;выход в дос mov ax,4c00h int 21h t1 proc ;процедура вывода текста, в DX уже есть строка mov ah,09h int 21h ret t1 endp end start
Объяснение кода листинга программы
Этот код на языке Assembler выполняет следующие действия:
- Запрос на ввод строки имени файла.
- Если введено что-то, код проверяет, является ли это именем файла. Если да, то в конце строки добавляется символ 0Dh.
- Код открывает файл для чтения и записи, используя введенное имя файла.
- Если файл не может быть открыт, код выводит сообщение об ошибке и закрывает файл.
- Если файл успешно открыт, код начинает цикл чтения и записи данных из файла в буфер.
- В цикле, каждый символ из файла выводится на экран и записывается обратно в файл.
- Когда достигается конец строки, код выводит сообщение об успешном завершении операции.
- Если в процессе чтения или записи возникают ошибки, код закрывает файлы и выводит сообщение об ошибке.
- В конце работы программы, код закрывает оба файла и завершает работу.