.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
.model small
.stack
.data
;const's
F_READ EQU 0
F_WRITE EQU 1
F_RDWR EQU 2
;messages
dos_ db 'Введите имя DOS-файла: $'
win_ db 'Введите имя WIN-файла: $'
_info db 10,13,'"DOS-to-WINDOWS" text file converter v1.1',10,13
db 'Written by Serg Lisin, Russia, 8 September 2002$'
;errormessages
doserr db 'DOS-файл не найден!$'
ERRlen db 10,13, 'Длина DOS-файла больше 65535 байт!$'
;variables
DOSfile db 128 dup (?)
WINfile db 128 dup (?)
READbuf db 00
DOShnd dw ?
WINhnd dw ?
Fileptr dw 0000
DOSlen dw 0000
;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
.code
start:
main PROC near
mov ax,@data
mov ds,ax
mov es,ax
mov ah,03h
int 10h
call begdos ;спросим имя DOS-файла
mov al,F_READ ;al -accsess type code "read only"
call _FDOSopen ;откроем файл для чтения
mov [DOShnd],ax ;сохраним дескриптор файла
mov bx,ax
call _Flen ;вычислим длину DOS-файла
call begwin ;спросим имя WIN-файла
mov al,F_WRITE ;al -access type code "write only"
call _FWINopen ;откроем файл для записи
mov [WINhnd],ax ; и сохраним дескриптор файла
_lop:
call _FDOSread ;прочитаем байт,
call _Convert ;перекодируем и
call _FWINwrite ;запишем байт
mov bx,[DOShnd] ;переместим
mov dx,[Fileptr];указатель
call _Fseek ;на одну позицию в DOS-файле,
mov bx,WINhnd ;и в WIN-файле
mov dx,[Fileptr];тоже
call _Fseek ;передвинемся
mov ax,[Fileptr] ;ax -указатель
mov dx,[DOSlen] ;dx -длина DOS-файла
cmp ax,dx ;сравним
jz short _exx_ ;если равно тогда выходим в DOS
inc ax ;если нет увеличим указатель на 1
mov [Fileptr],ax ;и поместим его на место
jmp short _lop ;уходим на след. виток
_exx_:
call prtinfo
mov ah,4Ch
int 21h
main ENDP
;---------------------------------------------
;процедуры ввода имен файлов
;---------------------------------------------
begdos PROC near
lea dx,dos_ ;Запрос имени DOS-файла
mov ah,09
int 21h ;печать по функции 09h
lea dx,DOSfile ;dx на буфер
mov bx,1 ;bx-дескриптор устройства(1-стандартный ввод)
mov cx,80 ;cx-длина
mov ah,3Fh ;3F - DOS service "read from file or device"
mov al,00
int 21h ;call DOS service
lea di,DOSfile
mov cx,80
cld
mov al,13
repnz scasb
mov byte ptr es:[di],00 ;затрем нулями код возврата каретки
mov byte ptr es:[di-1],00 ;и перевода строки
ret
begdos ENDP
begwin PROC near
lea dx,win_
mov ax,0900h
int 21h
lea dx,WINfile
mov bx,1
mov cx,80
mov ah,3Fh
mov al,0
int 21h
lea di,WINfile
mov cx,80
cld
mov al,13
repnz scasb
mov byte ptr es:[di],00
mov byte ptr es:[di-1],00
ret
begwin ENDP
_FDOSopen PROC near ;процедура открытия файла
; На входе: al = access type code, DS:DX указывает на имя файла
; На выходе: if CF set we have failed, else ax == Дескриптору файла
lea dx,ds:[DOSfile] ; point DS:DX to file name string
mov ah,3Dh ; select "open file" DOS service
int 21h ; call DOS service
jnc short fopendone ; if CF set we have failed
lea dx,doserr ;покажем
mov ah,09h ;сообщение
int 21h ;об ошибке,
call beep ;свистнем
mov ah,4Ch ;и выйдем в DOS
int 21h
fopendone:
ret ;если все ОК то вернемся без проблем
_FDOSopen ENDP
_FWINopen PROC near ;процедура открытия файла
lea dx,ds:[WINfile] ;DS:DX на имя файла
mov ah,3Dh ;3Dh-"open file" DOS service
int 21h ;call DOS service
jnc short fopendone ;if CF=1 файл не найден
creatfile: ;создадим нов. файл
mov ah,3Ch ;3Ch-"create file" DOS service
mov cx,0 ;
int 21h ;call DOS service
ret
_FWINopen ENDP
_FDOSread PROC near ;процедура чтения из файла
lea dx,es:[READbuf] ;ES:DX на буфер
mov bx,DOShnd ;bx- дескриптор файла
mov cx,1 ;кол-во читаемых байт
mov ah,3Fh ;3Fh - "read from file or device" DOS service
int 21h ;call DOS service
ret
_FDOSread ENDP
_Convert PROC near
xor ax,ax
mov al,ds:[READbuf] ;al -код символа (1251)
push ax
pop dx ;закинем код в bx
cmp dx,127 ;проверим
jg _work ;если код > 127, тогда обработаем
ret ;если меньше, тогда выйдем
_work:
sub dx,128
push dx
pop ax
lea bx,cp866
xlatb
mov ds:[READbuf],al
ret
_Convert ENDP
_FWINwrite PROC near ;процедура записи в файл
lea dx,es:[READbuf] ;ES:DX на буфер
mov bx,WINhnd ;bx- дескриптор файла
mov cx,1 ;число записываемых байт
mov ah,40h ;40h -"write file" DOS service
int 21h ;call DOS service
ret
_FWINwrite ENDP
_Fseek PROC near ;процедура перемещения указателя чтения/записи
;на входе: bx= дескриптору файла, al= режиму установки указателя
; dx= указателю
;на выходе: dx= смещению, куда реально установился указатель
mov ah,42h
mov al,0 ;"from start of file" method
xor cx,cx
mov dx,Fileptr
int 21h
cmp dx,cx
jz short thatsok
call beep
mov ah,4Ch
int 21h
thatsok:
ret
_Fseek ENDP
_Flen PROC near ;процедура определения длины файла
mov ah,42h ;"move file ptr" DOS service
mov al,2 ;"from end of file" method
xor cx,cx ;cx обнулим
xor dx,dx ; и dx тоже
int 21h
cmp dx,00
jnz short _errlen
mov ds:[DOSlen],ax
jmp short filelendone
_errlen:
lea dx,ERRlen
mov ah,09h
int 21h
call beep
mov ah,4Ch
int 21h
filelendone:
mov ah,42h
mov al,0
mov dx,Fileptr
xor cx,cx
int 21h
ret
_Flen ENDP
;---------------------------
beep PROC near
mov ax,0E07h
int 10h
ret
beep ENDP
prtinfo PROC near
lea dx,_info
mov ah,09h
int 21h
ret
prtinfo ENDP
END start