Authorization

.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