PDA

Показать полную графическую версию : [решено] Запись в файл


pogo
18-11-2010, 15:18
Люди добрые и знающие помогите пожалуйста
есть задача:
Программа просит ввести строку. Строка - слова разделённые одним или несколькими пробелами.
Удалить лишние пробелы (вначале строки, в конце строки, 1 пробел между словами).
Результат вывести на экран и записать в файл (файл создаётся в процессе)

Я тут написал часть программы:
.MODEL small ;отводим под стек и под данные по 64Кб
.STACK 100h ;отмечаем начало сегмента стека
.DATA ;отмечаем начало сегмента данных
NL db 0Ah, 0Dh, '$'
Buf DB 255, 0, 256 DUP (0) ;
.CODE ;отмечаем начало сегмента кодов
main PROC
mov ax,@data ;копируем адрес
mov ds,ax ;сегмента данных
mov dx,offset Buf ;считываем строку с клавиатуры
mov ah,0Ah
int 21h
xor cx,cx
mov al,[Buf+1] ;если считано 0 байт, то выход из
mov cl,al ;задаем количество повторений (длина строки)
test al,al ;программы
jz Exit
mov ah,09h
mov dx,offset NL ;перейти на следующую строку
int 21h
mov si,offset Buf+2
mov dh,0Dh ;подготовка - суём в регистр символ,
;которого не может быть во введённой строке

tmp:
mov dl,[si]
cmp dl,' '
jne Cycle1
inc si
dec cx
jmp tmp


Cycle:
mov dl,[si] ;считать символ
Cycle1:
cmp dl,' ' ;сравнить с пробелом
jne Print ;если не пробел - вывести
cmp dx,' ' ;а если пробел - то предыдущий был пробел или нет?
je NextChar ;если два пробела подряд - не печатаем
jne Print
Print:
mov ah,02h ;выбор функции 2
int 21h ;вызов DOS
NextChar:
mov dh,dl ;сохранить текущий символ для теста на следующем витке
inc si ;перейти к следующему символу
loop Cycle
Exit:
mov AX,4C00h ;выход
int 21h ;из программы
main ENDP
END main

Программа удаляет пробелы вначале строки и делает 1 пробел между словами.
Помогите пожалуйста удалить последние пробелы, а главное записать всё это дело
в файл...
В ассемблере не силён, погуглив в принципе нашёл как работать с файлами...
Но у меня ничего не получилось, по сюда даже не писал мои попытки работать с файлами,
ибо сам посидел, посмотрел и понял, что это бред.
Заранее спасибо!!

Admiral
18-11-2010, 16:36
pogo, задачу нужно решить именно под DOS (для иллюстрации процесса с академической точки зрения, судя по коду это TASM)? Или же нужна именно такая программа, и для ОС отличной от DOS?

Если на второе да, и ОС для которой нужно решение - MS Windows, то для решения можно воспользоваться функциями CreateFile\WriteFile\CloseHandle.
Если нужен именно под DOS, то задача сведётся к поиску нужных прерываний по работе с файлами.

pogo
18-11-2010, 17:26
да использую tasm и tlink
Надо именно под DOS
да и прерывания в инете найти не проблема введя в любом поисковике ассемблер работа с файлами он всё выдаст...
у меня проблема именно с реализацией этих прерываний в коде программы...
помогите пожалуйста дописать прогу

pogo
19-11-2010, 13:02
Что на таком большом форуме никто ассемблера не знает?((

ganselo
19-11-2010, 16:52
Что на таком большом форуме никто ассемблера не знает?(( »
тебе на wasm.ru

Admiral
19-11-2010, 17:13
pogo, вот пример http://subscribe.ru/archive/comp.prog.assembler/201006/26170402.html
Исключительно по теме:
TITLE Write 2 File Example

;Запись в файл

DOSSEG
.MODEL TINY
.STACK 100h
.DATA
szFileName DB 'My file.txt', '0'
msgSize = $-szFileName
.CODE
.386
ENTRY PROC NEAR
mov ax, @data
mov ds, ax

;создаём файл
mov ah, 3Ch ;Запись в файл или устройство
lea dx, szFileName ; эквивалентно -> mov dx, offset szFileName
xor cx, cx
int 21h
;считаем что проблем с созданием не возникло (а так нужна проверка)
mov bx, ax ; сохраняем описатель (handle) файла в bx
;пишем в файл
mov ah, 40h
lea dx, szFileName
mov cx, msgSize
int 21h
;закрываем файл
mov ah, 3Eh
int 21h

mov ax, 4c00h
int 21h
ENTRY ENDP
END
Создаётся файл с именем My file.txt с таким же содержанием + символ окончания строки.

pogo
19-11-2010, 18:01
Дошёл до того, что сделал 1 часть с пробелами:

.MODEL small ;отводим под стек и под данные по 64Кб
.STACK 100h ;отмечаем начало сегмента стека
.386
.DATA ;отмечаем начало сегмента данных
NL db 0Ah, 0Dh, '$'
Buf DB 255, 0, 256 DUP (0) ;
hFile dw ?
Filename db 'file.txt',0
.CODE ;отмечаем начало сегмента кодов
main PROC
mov ax,@data ;копируем адрес
mov ds,ax ;сегмента данных

mov dx, offset Buf
mov ah, 0Ah
int 21h ;запрашиваем строку

mov dx, offset NL
mov ah, 9h
int 21h ;переводим строку на экране, выводя CRLF

xor cx, cx
mov cl, [Buf+1]
test cl, cl
jz Exit ;проверяем длину строки - если пустая, то выходим

; mov si, offset Buf+2 ;если не пустая - то будем искать пробелы
; add Buf+2,cl
add bx, offset Buf+1
add bl, cl
mov si, bx
last:
mov dl,[si]
cmp dl,' '
jne tmp
dec si
dec cx
jmp last


tmp: mov si, offset Buf+2

first: mov dl,[si]
cmp dl,' '
jne Cycle
inc si
dec cx
jmp first

Cycle:
mov dl, [si] ;берём очередной байт
cmp dl, ' ' ;сравниваем с пробелом
jne Print
cmp dx,' ' ;а если пробел - то предыдущий был пробел или нет?
je NextChar ;если два пробела подряд - не печатаем

Print:
mov ah,02h ;выбор функции 2
int 21h ;вызов DOS

NextChar:
mov dh,dl ;сохранить текущий символ для теста на следующем витке
inc si ;перейти к следующему символу

loop Cycle


Exit:
mov ax, 4c00h
int 21h ;выходим из программы

main ENDP
END main


как с файлом сделать теоретически я представляю,
взять полученную строку и посимвольно записать её в файл...
или записать всё в переменную, что бы в ней получилась обработанная строка...
Но я вообще не поднимаю как это в Ассемблере реализовать ((
я не понимаю как вообще в файл запись происходит...

pogo
24-11-2010, 09:15
Вот готовый рабочий код программы:
Программа просит ввести строку. Строка - слова разделённые 1 или несколькими пробелами, удалить лишние пробелы (вначале строки, в конце строки, 1 пробел между словами)
Результат вывести на экран и записать в файл (файл создаётся в процессе). Запись в файл организовать в процедуре.


.MODEL small ;отводим под стек и под данные по 64Кб
.STACK 100h ;отмечаем начало сегмента стека
.386
.DATA ;отмечаем начало сегмента данных
NL db 0Ah, 0Dh, '$'
Buf DB 255, 0, 256 DUP (0) ;
hFile db 300 dup(?)
Filename db 'file.txt',0
.CODE ;отмечаем начало сегмента кодов
main PROC
mov ax,@data ;копируем адрес
mov ds,ax ;сегмента данных

mov dx, offset Buf
mov ah, 0Ah
int 21h ;запрашиваем строку

mov dx, offset NL
mov ah, 9h
int 21h ;переводим строку на экране, выводя CRLF

xor cx, cx
mov cl, [Buf+1]
test cl, cl
jz Exit ;проверяем длину строки - если пустая, то выходим

add bx, offset Buf+1
add bl, cl
mov si, bx
last:
mov dl,[si]
cmp dl,' '
jne tmp
dec si
dec cx
jmp last


tmp: mov si, offset Buf+2

first: mov dl,[si]
cmp dl,' '
jne Cycle
inc si
dec cx
jmp first


Cycle: lea di, hFile
mov bx,0

Cycle1: mov dl, [si] ;берём очередной байт
cmp dl, ' ' ;сравниваем с пробелом
jne Print
cmp dx,' ' ;а если пробел - то предыдущий был пробел или нет?
je NextChar ;если два пробела подряд - не печатаем

Print:
mov [di], dl
inc di
mov ah,02h ;выбор функции 2
int 21h ;вызов DOS
inc bx

NextChar:
mov dh,dl ;сохранить текущий символ для теста на следующем витке
inc si ;перейти к следующему символу

loop Cycle1

push bx

mov ah, 3Ch ;если же добрались до конца - будем сохранять.
mov dx, offset Filename
xor cx, cx
int 21h ;создаём файл

pop si

push offset hFile
call vivod

mov ah, 3eh
int 21h ;закрываем файл

Exit:
mov ax, 4c00h
int 21h ;выходим из программы

main ENDP

vivod proc
mov bx, ax
mov ah, 40h
mov cx, si
mov bp, sp
add bp, 2
mov dx, [bp]
int 21h
ret
vivod endp
END main


Может кому пригодится ))




© OSzone.net 2001-2012