.model medium
.stack
.fardata
Buffer db 32768 dup (?) ;буфер для декодирования
.data
;const's
F_READ EQU 0
F_WRITE EQU 1
F_RDWR EQU 2
;messages
Mes1 db 10,13,'Введите имя DOS-файла: $'
Mes2 db 10,13,'Введите имя WIN-файла: $'
InfoMes1 db 10,10,13,'"DOS-to-WINDOWS" text file converter v1.2 .',10,13
db 'Written by Serg Lisin, Russia, 27 January 2003.$'
;errormessages
ErrMes1 db 10,13,'DOS-файл не найден!$'
ErrMes2 db 10,13,'WIN-файл не найден!$'
WrAlMes db 10,13,'Ошибка позиционирования в файле!$'
AccDMes db 10,13,'Доступ закрыт!$'
WrDesMes db 10,13,'Неверный дескриптор файла!$'
;variables
InpFileN db 16 dup (?) ;имя входного файла
OutFileN db 16 dup (?) ;имя выходного файла
InpDescr dw 0 ;дескриптор входного файла
OutDescr dw 0 ;дескриптор выходного файла
InpFileLn dd 0 ;длина входного файла
RLen dw 0
;codepage
cp866 db 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207
db 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223
db 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239
db 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32
db 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32
db 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32
db 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255
db 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32
.486p
.code
Main PROC near
mov ax,@data
mov ds,ax
mov es,ax
mov ax,@fardata
mov fs,ax
mov ah,03h
int 10h
;запрос имени входного файла
lea dx,Mes1
call PrtString
;ввод имени входного файла
lea dx,InpFileN
call InpString
lea dx,InpFileN ;point DS:DX to file name string
mov al,F_READ ;только чтение
call OpenFile ;открываем
jc ErrInpFile ;if CF we have failed
mov InpDescr,ax ;else save descriptor
;запрос имени выходного файла
lea dx,Mes2
call PrtString
;ввод имени выходного файла
lea dx,OutFileN
call InpString
lea dx,OutFileN ;point DS:DX to file name string
mov al,F_WRITE ;только запись
call OpenFile ;открываем
mov OutDescr,ax ;save descriptor
jnc Flength ;if CF we have failed
ErrOutFile1: ;если файл не сществует - создадим
mov ah,3Ch ;3Ch-"create file" DOS service
mov cx,0
int 21h ;call DOS service
mov OutDescr,ax ;сохраним дескриптор
;расчет длины входного файла
Flength:
mov bx,InpDescr ;bx - дескриптор файла
call InpFileLen ;вычислим длину файла
jc ErrFileLen ;обработка ошибки
;цикл чтение - перекодировка - запись
RWCycle:
call ReadInpFile ;читаем входной файл в буфер
jc ErrRead ;обработка ошибки
mov RLen,ax ;ax - кол-во реально прочитанных байт для записи
call ConvertBuffer ;конвертируем
call WriteOutFile ;пишем буфер в выходной файл
jc ErrWrite ;обработка ошибки
cwde ;расширяем ax в eax для контроля конца вых. файла
sub InpFileLn,eax ;вычитаем
cmp InpFileLn,0 ;if длина = 0
jle Exit ;then Exit
jmp RWCycle ;else повторим цикл
;обработка ошибок
ErrInpFile:
lea dx,ErrMes1
call PrtString
jmp short Exit
ErrOutFile:
lea dx,ErrMes2
call PrtString
jmp Exit
ErrFileLen:
cmp ax,1
je WrAl
cmp ax,6
je WrnDes
jmp Exit
ErrRead:
cmp ax,5
je AccD
cmp ax,6
je WrnDes
jmp Exit
ErrWrite:
cmp ax,5
je AccD
cmp ax,6
je WrnDes
jmp Exit
WrAl:
lea dx,WrAlMes
call PrtString
jmp Exit
AccD:
lea dx,AccDMes
call PrtString
jmp Exit
WrnDes:
lea dx,WrDesMes
call PrtString
jmp Exit
Exit:
lea dx,InfoMes1
call PrtString
mov ah,4Ch
int 21h
Main ENDP
;============================================================================
;Процедура ввода строки с клавиатуры
;на входе: dx - указатель на строку-буфер
;на выходе: ничего
;============================================================================
InpString PROC near
push dx ;спрячем указатель в стек для последующей коррекции
mov bx,1 ;bx-дескриптор устройства(1-стандартный ввод)
mov cx,14 ;cx-длина
mov ah,3Fh ;3F - DOS service "read from file or device"
mov al,00
int 21h ;call DOS service
pop di ;di - указатель на строку-приемник
mov cx,16 ;cx - длина
cld ;вперед
mov al,13 ;символ ВК
repnz scasb ;ищем...
mov byte ptr es:[di],00 ;затрем нулями код возврата каретки
mov byte ptr es:[di-1],00 ;и перевода строки
ret
InpString ENDP
;============================================================================
;Процедура открытия файла
;на входе: al = access type code, DS:DX указывает на имя файла
;на выходе: if CF=1 - ошибка else ax = дескриптору файла
;============================================================================
OpenFile PROC near
mov ah,3Dh ;"open file" DOS service
int 21h ;call DOS service
ret
OpenFile ENDP
;============================================================================
;Процедура определения длины файла
;на входе: bx = дескриптору файла
;на выходе: CF=1 - ошибка else edx = длине файла
;============================================================================
InpFileLen PROC near
push bx ;дескриптор файла - в bx
mov al,2
xor cx,cx
xor dx,dx ;CX:DX =0 - нулевое смещение
mov ah,42h
int 21h ;в DX:AX возвращается длина файла в байтах
jc ErrRet ;переход если ошибка
; shl eax,16 ;формируем полную длину в edx
; shld edx,eax,16
push dx
push ax
pop edx
mov InpFileLn,edx
pop bx ;устанавливаем указатель на начало файла
mov al,0
xor cx,cx
xor dx,dx ;CX:DX =0 - нулевое смещение
mov ah,42h
int 21h ;текущий указатель в начале файла
ErrRet:
ret
InpFileLen ENDP
;============================================================================
;процедура замены символов в буфере символами из таблицы
;============================================================================
ConvertBuffer PROC near
mov cx,32767
xor si,si ;si - указатель на символ в буфере
NextChar:
xor ax,ax
mov al,fs:[Buffer+si] ;al - символ из буфера
push ax
pop dx ;закинем код в dx
cmp dx,127 ;if al > 127 then
jg Convert ;goto Convert
inc si ;else увеличим указатель
loop NextChar ;и примем след. символ
jmp AllConv ;если буфер весь - возврат
Convert:
sub dx,128 ;вычислим указатель на символ замены в таблице
push dx ;перекинем указатель в вч
pop ax ;в ax для команды xlatb
lea bx,cp866 ;bx => на начало таблицы
xlat ;заменим символ
mov fs:[Buffer+si],al ;и поместим в буфер
inc si ;увеличим указатель
loop NextChar ;и повторим весь цикл
AllConv:
ret
ConvertBuffer ENDP
;============================================================================
;процедура чтения входного файла
;============================================================================
ReadInpFile PROC near
push ds ;т.к. буфер находится в доп.сегменте данных
push fs ;подставим сег.адрес буфера в DS
pop ds
lea dx,Buffer ;ds:dx - указатель на буфер
mov bx,es:[InpDescr] ;bx - дескриптор входного файла
mov cx,32767 ;сх - кол-во читаемых байт
mov ah,3Fh
int 21h
pop ds ;воостановим DS
ret
ReadInpFile ENDP
;============================================================================
;процедура записи выходного файла
;============================================================================
WriteOutFile PROC near
push ds
push fs
pop ds
lea dx,Buffer
mov bx,es:[OutDescr]
mov cx,es:[RLen] ;RLen - число реально прочитанных байт для
mov ah,40h ;коректной записи
int 21h
pop ds
ret
WriteOutFile ENDP
PrtString PROC near
mov ah,09h
int 21h
ret
PrtString ENDP
END