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