Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

RFpro.ru: Ассемблер? Это просто! Учимся программировать


Хостинг портала RFpro.ru:
Московский хостер
Профессиональный ХОСТИНГ на базе Linux x64 и Windows x64

РАССЫЛКИ ПОРТАЛА RFPRO.RU

Чемпионы рейтинга экспертов в этой рассылке

Boriss
Статус: Академик
Рейтинг: 2366
∙ повысить рейтинг »
_Ayl_
Статус: Профессионал
Рейтинг: 1849
∙ повысить рейтинг »
vladisslav
Статус: 6-й класс
Рейтинг: 1227
∙ повысить рейтинг »

/ КОМПЬЮТЕРЫ И ПО / Программирование / Assembler (Ассемблер)

Номер выпуска:1343
Дата выхода:25.05.2010, 21:30
Администратор рассылки:Лысков Игорь Витальевич, Модератор
Подписчиков / экспертов:266 / 63
Вопросов / ответов:2 / 2
IRC-канал по теме:#assembler

Вопрос № 178504: Доброго времени суток, уважаемые эксперты! Прошу помочь с такой задачей: необходимо написать резидентную программу, которая через каждую минуту выводит сообщение "Привет" и не мешает работе пользователя. DOS, TASM. ...


Вопрос № 178509: Доброго времени суток, уважаемые эксперты! Прошу помочь с такой задачей: необходима программа текстового редактора.Дополнительные условия не обозначены. DOS, TASM.Заранее спасибо....

Вопрос № 178504:

Доброго времени суток, уважаемые эксперты!
Прошу помочь с такой задачей:
необходимо написать резидентную программу, которая через каждую минуту выводит сообщение "Привет" и не мешает работе пользователя.
DOS, TASM.

Отправлен: 19.05.2010, 21:05
Вопрос задал: Виктор Никанорович, Посетитель
Всего ответов: 1
Страница вопроса »


Отвечает Зенченко Константин Николаевич, Модератор :
Здравствуйте, Виктор Никанорович.

Смотрите приложение. Код TASM 2.00. Запускал дополнительно ещё и редактор EDIT, т.к. в только в CMD - ХР, результата нет.



Вопросы задавайте в мини-форум.
Удачи!

Приложение:

-----
Итерация от человека. Рекурсия — от Бога. — Л. Питер Дойч

Ответ отправил: Зенченко Константин Николаевич, Модератор
Ответ отправлен: 20.05.2010, 16:44
Номер ответа: 261524
Украина, Киев
Тел.: +38-097-953-66-19
Адрес: Украина, Киев

Оценка ответа: 5

Вам помог ответ? Пожалуйста, поблагодарите эксперта за это!
Как сказать этому эксперту "спасибо"?
  • Отправить SMS #thank 261524 на номер 1151 (Россия) | Еще номера »
  • Отправить WebMoney:

  • Вопрос № 178509:

    Доброго времени суток, уважаемые эксперты! Прошу помочь с такой задачей: необходима программа текстового редактора.Дополнительные условия не обозначены. DOS, TASM.Заранее спасибо.

    Отправлен: 19.05.2010, 21:17
    Вопрос задал: Виктор Никанорович, Посетитель
    Всего ответов: 1
    Страница вопроса »


    Отвечает Лысков Игорь Витальевич, Модератор :
    Здравствуйте, Виктор Никанорович.
    Вот Вам текстовый редактор
    Код:
    ;Текстовый редактор
    ;Распределение сегментов: DS=SS=сегмент данных, ES=видеобуфер

    .model small, C ;модель памяти + соглашение о передаче параметров
    .286 ;чтобы можно было посылать в стек числа
    .code ;сегмент кода
    .startup ;точка входа
    call init ;инициализация
    call PrWin, 0, 0, XSize, YSize, DOUBLE, MainColor ;рисуем окно с рамкой
    call PrHelpMess ;выводим строку "F1 - помощь"

    call SetCursor ;установим курсор в позицию (1,1)
    call GetFile ;читаем файл, если имя файла задано параметром

    Redraw: ;сюда приходим, когда надо перерисовать содержимое буфера
    call SetName ;пишем имя файла

    mov ax, XSize ;выводим содержимое буфера на экран
    dec ax
    mov cx, YSize
    dec cx
    mov dx, UpLine
    push ds
    mov ds, FileSeg
    call PrText, 1, 1, ax, cx, dx
    pop ds

    NewCursor: ;сюда приходим, когда надо только поменять позицию курсора
    call SetCursor
    KeyLoop: ;цикл ожидания нажатия на клавишу
    mov ah,0 ;al=кон, ah=скан-код
    int 16h

    lea di, KeyTable ;адрес таблицы отрабатываемых кодов
    mov cx, KeyTableLen ;длина
    SearchKey_loop:
    cmp ah, [di] ;сравниваем скан-код
    je KeyFound ;нашли код
    inc di
    loop SearchKey_loop ;по всей таблице
    ;дальше нас интересуют только символьные коды
    cmp al, ' ' ;управляющие игнорируем
    jae KeyInsert ;вставляем код
    jmp KeyLoop
    KeyFound: ;отработка кода
    sub di, offset KeyTable
    shl di, 1 ;di - смещение в таблице PrgTable
    jmp PrgTable[di] ;на отработку

    KeyInsert: ;вставка символа
    cmp FileLen, 0ffffh ;проверка на длину (макс = 0ffffh)
    je KeyLoop< br> mov fChange, 1 ;содержимое поменялось
    ;освободим места для нового символа, для этого сдвинем на 1 байт
    mov si, FileLen ;смещение конца
    lea di, [si+1] ;на 1 дальше
    xor bx, bx
    mov bl, XFile ;позиция в текущей строке
    add bx, CurLine ;+смещение строки в файле (смещение, куда надо вставить)
    mov cx, di
    sub cx, bx ;количество копируемых байт
    push ds es
    mov es, FileSeg
    mov ds, FileSeg ;в рабочем буфере
    std ;в обратном порядке
    rep movsb ;копируем
    cld ;воостановим прямой порядок цепочечных команд
    mov [bx], al ;вставляем введенный код на его место
    pop es ds
    inc FileLen ;инкремент длины файла
    call PressedKeyRight ;перемещаем курсор вправо
    jmp Redraw ;не перерисовку
    KeyEnter: ;вставка перевода строки, а точнее двух кодов 0dh и 0ah
    cmp FileLen, 0fffeh ;проверка на длину (макс = 0fffeh)
    jae KeyLoop
    mov fChange, 1 ;содержимое поменялось
    ;освободим места для двух символов, для э того сдвинем на 2 байта
    mov si, FileLen ;смещение конца
    lea di, [si+2] ;на 2 дальше
    xor bx, bx
    mov bl, XFile ;позиция в текущей строке
    add bx, CurLine ;+смещение строки в файле (смещение, куда надо вставить)
    mov cx, di
    sub cx, bx ;количество копируемых байт
    push ds es
    mov es, FileSeg
    mov ds, FileSeg ;в рабочем буфере
    std ;в обратном порядке
    rep movsb ;копируем
    cld ;воостановим прямой порядок цепочечных команд
    mov word ptr [bx], 0a0dh ;вставляем введенные коды на их место
    pop es ds
    add FileLen, 2 ;увеличиваем длину файлу
    call PressedKeyRight ;перемещаем курсор вправо
    to_Redraw: ;промежуточная метка, чтобы достать до метки < 128
    jmp Redraw ;не перерисовку
    to_KeyLoop: ;промежуточная метка, чтобы достать до метки < 128
    jmp KeyLoop
    finish: ;выход
    call exit
    KeyUp:
    call PressedKeyUp ;стрелка вверх
    jc to_KeyLoop ;ничего дополнительного не делать
    jz to_Redraw ;п ерерисовать
    jmp NewCursor ;поменять позицию курсора
    KeyLeft:
    call PressedKeyLeft ;стрелка влево
    jc to_KeyLoop
    jz to_ Redraw
    jmp NewCursor
    KeyRight:
    call PressedKeyRight ;стрелка вправо
    jc to_KeyLoop
    jz to_Redraw
    jmp NewCursor
    Keydown:
    call PressedKeyDown ;стрелка вниз
    jc to_KeyLoop
    jz to_Redraw
    jmp NewCursor
    KeyHelp:
    call Help ;F1
    to_NewCursor:
    jmp NewCursor
    KeyRead:
    call ReadFile ;F3
    jc to_NewCursor
    jmp Redraw
    KeyWrite:
    call WriteFile ;F2
    jc to_NewCursor
    jmp Redraw
    KeyBack:
    call BackSpace ;BackSpace
    jc to_KeyLoop
    jmp Redraw

    ;расчет позиции курсора для строки текста, учитывается табуляция
    ;bx - до какой позиции смотрим
    CalcXtab proc
    push ds
    xor cx, cx ;счетчик позиции на экране
    mov si, CurLine ;текущая строка
    mov ds, FileSeg
    dec bx ;адрес предыдущего байта
    CX_loop:
    cmp si, bx ;дошли до bx
    jge CX_ret ;на выход, в CX искомая позиция курсора
    lodsb ;очередной байт
    inc cx ;посчитаем
    cmp al, 9 ;табуляция?
    jne CX_loop ;для обычн ого символа просто идем на следующий
    mov ax, cx ;табуляцию расширяем до 8-й позиции
    and ax, 7 ;ax = x mod 8
    sub ax, 8
    neg ax ;ax = 8 - (x mod 8)
    add cx, ax ;ax - число пробелов, чтобы табуляция встала на позиции, кратной 8
    jmp CX_loop ;продолжаем
    CX_ret:
    mov ax, cx
    pop ds
    mov XScreen, al ;сохраним новую позицию курсора
    ret
    CalcXtab endp

    ;расчет позиции курсора для строки текста, учитывается табуляция
    ;отличие от предыдузей в том, что здесь проверяем на старую позицию курсора
    ;используется в переходе на строку вниз/вверх
    CalcXXtab proc
    push ds
    mov dl, XScreen ;старая позиция курсора
    mov si, CurLine ;текущая строка
    mov ds, FileSeg
    xor bx, bx ;индекс в текущей строке
    xor cx, cx ;сl-текущая позиция в строке, ch-промежуточное значение позиции
    CXX_loop:
    cmp ch, dl ;дошли до старой позиции
    ja CXX_ret1
    mov cl, ch ;нет, сохраним, как текущую
    mov al, [bx+si] ;читаем байт< br> cmp al, 0dh ;конец строки?
    je CXX_ret ;да, это и будет новая позиция на экране
    cmp al, 9 ;табуляция?
    jne CXX_next ;нет - на следующий
    mov al, cl ;расширяем табуляцию пробелами
    and al, 7
    sub al, 7
    sub ch, al
    CXX_next:
    inc ch ;инкремент позиции на экране
    inc bx ;инкремент позиции в файле
    jmp CXX_loop
    CXX_ret1:
    dec bl ;в случае, когда табуляция перескакивает, то на 1 меньше
    CXX_ret:
    pop ds
    mov XFile, bl ;сохраним позицию в файле
    mov XScreen, cl ;и на экране
    ret
    CalcXXtab endp

    ;отработка клавиши "влево"
    PressedKeyLeft proc
    mov ax, CurLine ;в первой позиции ничего не делаем
    or ax, UpLine
    or al, XFile
    jnz KL_Change
    KL_NoChange:
    stc
    ret
    KL_Change:
    xor ax, ax
    mov al, XFile
    add ax, CurLine ;ax - позиция текущего символа в файле
    push ds
    mov ds, FileSeg
    mov bx, ax
    mov dl, [bx-1] ;предыдущий символ
    pop ds

    cmp dl, 0a h ;мы в начале строки?
    je KL_eol ;становимся в конец предыдущей
    dec XFile ;уменьшаем на 1 позицию в строке
    cmp dl, 9 ;предыдущий символ - табуляция?
    je KL_tab ;отрабатываем
    dec XScreen ;для обычного символа просто уменьшаем позицию на экране
    KL_NewCursor:
    or al, 1 ;Z=0 для установки курсора
    clc ;для отработки
    ret
    KL_tab:
    call CalcXtab ;посчитаем новую позицию курсора на экране
    jmp KL_NewCursor
    KL_eol: ;переходим в конец строки выше
    push ds
    mov ds, FileSeg
    dec bx ;bx - позиция в файле символа 0ah

    lea di, [bx-1] ;di - позиция 0dh
    KL_eol_loop: ;ищем начало строки
    dec bx ;на предыдущий символ
    test bx, bx ;для первой строки дойдем до 0
    jz KL_set_CurLine ;начало первой строки
    mov al, [bx] ;читаем символ
    cmp al, 0ah ;0ah?
    jne KL_eol_loop
    inc bx ;нашли 0ah, следующий - начало строки
    KL_set_CurLine:
    pop ds

    mov CurLine, bx ;сохраним адрес, как адрес тек ущей строки

    mov bx, di ;посчитаем позицию на экране
    sub bx, CurLine ;bx - длина строки
    mov XFile, bl ;запомним, как позиц ию в строке файла
    lea bx, [di+1] ;адрес конца строки
    call CalcXtab ;считаем позицию на экране

    KL_scroll: ;если есть необходимость, делаем скроллинг на одну строку
    dec YFile ;уменьшим номер строки в файле
    sub YScreen, 1 ;уменьшим номер строки на экране
    ;(отнимаем 1, а не dec - чтобы отработался флаг С)
    jge KL_NewCursor ;если нет необходимости скроллировать, то выходим

    mov ax, CurLine ;устанавливаем новый адрес начала прорисовки
    mov UpLine, ax
    mov YScreen, 0 ;номер строки на экране = 0

    mov ax, 0701h ;скролинг на одну строку вниз
    mov cx, 0101h ;с позиции (1,1)
    mov dl, byte ptr XSize ;и все, что внутри рамки
    mov dh, byte ptr YSize
    sub dx, cx
    mov bh, byte ptr MainColor ;цвет фона
    int 10h
    mov ax, XSize ;выводим в первую строку экрана текущую строку файла
    dec ax
    mov dx, UpLine
    push ds
    mov ds, FileSeg
    call PrText, 1, 1, ax, 1, dx
    pop ds
    jmp KL_NewCursor
    PressedKeyL eft endp

    ;строка вверх
    PressedKeyUp proc
    mov ax, CurLine ;для первой строки ничего не делаем
    or ax, UpLine
    jnz KU_Change
    KU_NoChange:
    stc
    ret
    KU_Change:
    mov bx, CurLine ;начало текущей строки в файле

    push ds
    mov ds, FileSeg
    dec bx ;адрес 0ah предыдущей строки
    ;ищем начало предыдущей строки
    KU_eol_loop:
    dec bx
    test bx, bx ;для первой строки начало - bx=0
    jz KU_set_CurLine
    mov al, [bx] ;ищем начало строки, как адрес байта,
    cmp al, 0ah ; следующего за 0ah (строки, которая выше)
    jne KU_eol_loop
    inc bx ;начало строки
    KU_set_CurLine:
    pop ds
    mov CurLine, bx ;сохраним

    call CalcXXtab ;вычислим текущую позицию на экране

    jmp KL_scroll ;проскроллируем, если необходимо

    PressedKeyUp endp

    ;отработка клавиши "вправо"
    PressedKeyRight proc
    xor ax, ax ;если в позиции последнего символа,
    mov al, XFile ; то ничего не делаем
    add ax , CurLine
    cmp ax, FileLen
    jb KR_Change
    KR_NoChange:
    stc
    ret
    KR_Change:
    push ds
    mov ds, FileSeg
    mov bx, ax
    mov dl, [bx] ;символ в текущей позиции
    pop ds

    cmp dl, 0dh ;конец строки?
    je KR_eol ;да, переходим на следующую
    inc XFile ;нет, инкремент позиции в строке файла
    cmp dl, 9 ;если табуляция,
    je KR_tab ;то посчитать позицию на экране
    inc XScreen ;нет, просто инкремент позиции на экране
    KR_NewCursor:
    or al, 1 ;смена позиции курсора
    clc ;отработать
    ret
    KR_tab: ;табуляция
    xor ax, ax
    mov al, XScreen
    and ax, 7
    sub ax, 8 ;ax = (XScreen mod 8) - 8 < 0
    sub XScreen, al ;выравнять до позиции, кратной 8
    jmp KR_NewCursor
    KR_eol: ;переходим на следующую строку
    xor ax, ax
    mov al, XFile
    add ax, CurLine
    inc ax ;обойдем 0dh, 0ah
    inc ax

    mov CurLine, ax ;сохраним адрес, как начало новой строки

    mov XFile,0 ;начало строки в фай ле
    mov XScreen, 0 ;начало строки на экране

    KR_scroll: ;скроллинг на одну строку вниз, если необходимо
    inc YFile ;инкремент строки в файле
    inc YScreen ;инкрмент строки на экране
    xor ax, ax
    mov al, YScreen ;номер строки на экране
    mov cx, YSize
    dec cx ;максимальный номер строки + 1
    cmp ax, cx ;если меньше то скроллировать не надо
    jb KR_NewCursor
    dec YScreen ;вернем на номер последней строки
    ;найдем адрес второй строки для отображения
    mov bx, UpLine ;адрес первой строки на экране
    push ds
    mov ds, FileSeg
    KR_eol_loop: ;ищем 0ah в конце строки
    mov al, [bx]
    inc bx
    cmp al, 0ah
    jne KR_eol_loop
    pop ds
    mov UpLine, bx ;сохраним следующий адрес, как адрес верхней строки

    mov ax, 0601h ;скроллируем на одну строку вверх
    mov cx, 0101h
    mov dl, byte ptr XSize
    mov dh, byte ptr YSize
    sub dx, cx
    mov bh, byte ptr MainColor
    int 10h
    mov ax, XSize
    dec ax
    mo v cx, YSize
    dec cx
    mov dx, CurLine
    push ds
    mov ds, FileSeg ;выводим одну текущую строку в конце экрана
    call PrText, 1, cx, ax, 1, dx
    pop ds
    jmp KR_NewCursor
    PressedKeyRight endp

    ;строка вниз
    PressedKeyDown proc
    mov bx, CurLine ;пробуем найти 0ah, если не находим, то
    KD_eol_loop: ; то ничего не делаем
    cmp bx, FileLen
    jae KD_NoChange
    push ds
    mov ds, FileSeg
    mov al, [bx]
    pop ds
    inc bx
    cmp al, 0ah
    jne KD_eol_loop
    jmp KD_Change
    KD_NoChange:
    stc
    ret
    KD_Change:
    mov CurLine, bx ;сохраняем адрес байта за 0ah,
    ; как адрес текущей строки
    call CalcXXtab ;посчитаем позицию на экране для новой строки

    jmp KR_scroll ;на скроллирование, если надо

    PressedKeyDown endp

    ;отработка BackSpace
    BackSpace proc
    mov ax, CurLine ;для первого символа ничего не делаем
    or ax, UpLine
    or al, XFile
    jnz BS_Change
    BS_NoChange:
    stc
    ret
    BS_Change:
    mov fChange, 1 ;содержимое изменено
    call PressedKeyLeft ;курсор влево
    xor bx, bx
    mov bl, XFile
    add bx, CurLine ;текущая позиция в файле
    push ds ;копируем на 1 или на 2 позиции, затирая текущий символ
    push es
    mov es, FileSeg
    mov ds, FileSeg
    mov di, bx
    mov bx, 1 ;для обычного символа
    mov al, [di]
    cmp al, 0dh
    jne copy_back
    inc bx ;для конца строки bx = 2
    copy_back:
    lea si, [di+bx] ;адрес, откуда пишем
    mov cx, ss:Filelen
    sub cx, si
    inc cx ;число копируемых байт (вместе с завершающим 0)
    rep movsb ;копируем
    pop es
    pop ds
    dec di
    mov FileLen, di ;новая длина файла
    clc ;для прорисовки
    ret
    BackSpace endp

    ;рисуем окно (x1,y1)-(x2,y2) с двойной/одинарной рамкой и указанным цветом
    PrWin proc x1:word, y1:word, x2:word, y2:word, TableType:word, color:word
    local rows:word, cols:word

    mov ax, 0600h ;очищаем окно
    mov ch, byte ptr y1
    mov cl, byte ptr x1
    mov dh, byte ptr y2
    mov dl, byte ptr x2
    mov bh, byte ptr color
    int 10h

    mov si, TableType ;тип рамки ( 0,1)
    shl si, 1
    mov si, Borders[si] ;адрес таблицы псевдографики

    mov ax, Xsize ;вычисляем адрес начала вывода
    inc ax
    mul y1
    add ax, x1
    shl ax, 1
    mov di, ax ;адрес вывода в видеобуфер

    mov ax, y2 ;число строк
    sub ax, y1
    inc ax
    mov rows, ax

    mov ax, x2 ;число колонок
    sub ax, x1
    inc ax
    mov cols, ax

    mov bx, XSize
    inc bx
    shl bx, 1 ;длина строки для перехода на следующую строку

    mov ah, byte ptr color+1 ;цвет рамки
    push di
    mov al, LU[si] ;левый верхний уголок
    stosw
    mov cx, cols ;горизонталь
    dec cx
    dec cx
    mov dx, cx ;сохраним "внутренюю" длину колонок
    mov al, HH[si]
    rep stosw
    mov al, RU[si] ;правый верхний уголок
    stosw
    pop di
    add di, bx
    mov cx, rows
    dec cx
    dec cx ;число "средних" строк
    PW_RLoop: ;окаймим "средние" строки вертикалями
    push di
    mov al, VV[si]
    stosw
    add di, dx
    add di, dx
    stosw
    pop di
    add di, bx
    loop PW_RLoop
    mov al, LD[si] ;нижняя часть, левый нижний уголок
    stosw
    mov cx, dx
    mov al, HH[si] ;горизонталь
    rep stosw
    mov al, RD[si] ;правый нижний уголок
    stosw

    ret
    PrWin endp

    ;Установка курсора
    SetCursor proc
    push ax
    mov ah, 2
    mov dx, word ptr ss:XScreen ;x+y
    add dx, 0101h ;поправка на позицию (1,1)
    mov bh, 0
    int 10h
    pop ax
    ret
    SetCursor endp

    ;начальная инициализация
    init proc
    call GetParm ;вводим имя файла из строки параметров

    ;узнаем размер экрана по горизонтали
    mov ah, 0fh
    int 10h
    mov al, ah ;в ah - число текстовых колонок
    mov ah, 0
    dec ax
    mov Xsize, ax ;сохраним индекс последнего символа в строке экрана

    ;определим высоту экрана
    mov ax, 1130h
    int 10h
    mov al, dl ;в dl число строк - 1
    mov ah, 0
    mov Ysize, ax ;сохраним индекс последней строки экрана

    ;обнулим некоторые переменные
    mov fChange, 0
    mov CurLine, 0
    mov UpLine, 0
    mov XScreen, 0
    mov YScreen, 0
    mov XFile, 0
    mov YFile, 0

    ;зададим адрес сегмента для содержимого файла, как DS+1000h
    xor bx, bx
    mov ax, ds
    add ax, 1000h
    mov FileSeg, ax
    mov FileLen, bx ;длины 0
    push ds
    mov ds, ax
    mov [bx], bl ;первый символ - 0
    pop ds

    ;запомним позицию курсора
    mov ah, 3
    mov bh, 0
    int 10h
    mov PosOld, dx

    ;сохраним содержимое видеостраницы, чтобы потом восстановить
    mov ax, XSize
    mov cx, YSize
    inc ax
    inc cx
    mul cx
    mov cx, ax
    push ds
    push ds
    pop es
    mov ax, 0b800h
    mov ds, ax
    lea di, SaveScr
    xor si, si
    rep movsw
    pop ds

    ;настраиваем сегментный регистр es на видеобуфер
    mov ax, 0b800h
    mov es, ax
    ret
    init endp

    ;рассматриваем строку параметров, как имя файла
    GetParm proc
    mov si, 81h ;начало строки, длину по адресу 80h игнорируем,
    ; будем искать конец по 0dh
    lea di, FName ;сюда запишем имя файла
    GPSpaceLoop: ;сначала пропуст им разделители перед параметром
    mov al,es:[si] ;es адресует PSP
    inc si
    cmp al, 0dh
    je GPRet ;параметра нет
    cmp al, ' '
    je GPSpaceLoop
    cmp al, 9
    je GPSpaceLoop
    GPName: ;что-то нашли
    mov [di], al ;сохраняем
    inc di
    mov al,es:[si]
    inc si
    cmp al, 0dh ;продолжаем до 0dh
    je GPRet
    cmp al, ' ' ; или до разделителя
    je GPRet
    cmp al, 9
    jne GPName
    GPret:
    mov byte ptr [di], 0;закрываем строку нулем
    ret
    GetParm endp

    ;пишем имя файла вверху экрана
    SetName proc
    mov cx, XSize
    sub cx, 4 ;на всякий случай, ограничим длину
    lea si, FName ;имя файла
    cmp byte ptr [si],0 ;задано ли?
    jne SNPrName
    lea si, Default ;нет - считаем именем Default.txt
    SNPrName:
    mov di, 2 ;с позиции 1
    mov ah, byte ptr MainColor+1 ;цвет
    mov al, ' ' ;отделим пробелом
    stosw
    SNPrLoop:
    lodsb
    cmp al, 0
    je SNPrTail
    stosw
    loop SNPrLoop ;выведем строку имени
    SNPrTail:
    mov al, ' '
    stosw ;пробел
    dec cx
    mov al, BorderDouble + HH
    stosw
    dec cx
    cmp fChange, 0
    je SNFlagChange
    mov al, '*' ;признак изменения содержимого (* или черточка)
    SNFlagChange:
    stosw
    dec cx ;до конца, чтобы вытереть возможное старое, выведем черточки
    jcxz SNRet
    mov al, BorderDouble + HH
    SN_clear_loop:
    stosb
    inc di
    loop SN_clear_loop
    SNRet:
    ret
    SetName endp

    ;краткая помощь
    ;внутри 11 строк
    Help proc
    call MessageBox, offset sHelp, 11
    ret
    Help endp

    ;читаем файл по F3
    ReadFile proc
    cmp fChange, 0 ;было ли изменение?
    je RFContinue
    ;1 строку сообщения
    call MessageBox, offset sChanged, 1
    ;возвращается скан-код нажатой клавиши
    cmp ah, 15h ;Y
    jne RFRet ;не Y - не сохраняем
    RFContinue:
    ;запрос имени файла
    call NameBox,offset sReadFile, offset sFileName, offset FName
    jc RFRet ; Esc - отказ от чтения
    call GetFile ;читаем файл с именем FName
    mov fChange, 0 ;все обнуляем
    mov CurLine, 0
    mov UpLine, 0
    mov XScreen, 0
    mov YScreen, 0
    mov XFile, 0
    mov YFile, 0
    clc ;перерисовываем
    ret
    RFRet:
    stc
    ret
    ReadFile endp

    ;пишем файл по F2
    WriteFile proc
    ;запрос имени файла
    call NameBox,offset sWriteFile, offset sFileName, offset FName
    jc WFRet ;отказ по Esc
    call SetFile ;сохраняем файл
    mov fChange, 0 ;сброс флага изменения
    clc ;перерисуем
    WFRet:
    ret
    WriteFile endp

    ;читаем файл
    GetFile proc
    lea dx, FName
    cmp FName, 0
    jnz GFOpen
    lea dx, default
    GFOpen:
    mov si, dx ;сохраняем адрес имени (для сообщений)
    mov ax, 3d00h
    int 21h ;открываем на чтение
    jc GFOpenError ;ошибка открытия
    mov bx, ax ;описатель файла
    push ds
    mov ds, FileSeg
    xor dx, dx
    mov cx,0ffffh
    mov ah, 3fh
    int 21h ;читаем в сегмент да нный файла
    jc GFReadError ;ошибка чтения
    cmp ax, cx ;проверим размер файла (еще есть что читать, значит больше, чем надо)
    jz GFSizeError ;выведем ошибку
    mov si, ax ;длина как индекс конца
    mov byte ptr [si],0 ;запишем в конце нолик
    pop ds
    mov FileLen, ax ;сохраним длину файла

    mov fChange, 0 ;сбросим флаг изменения
    FNCloseFile:
    mov ah, 3eh
    int 21h ;закрываем файл
    ret
    ;сообщения об ошибках
    GFOpenError:
    cmp si, offset default
    je GFRet ;ошибку открытия файла default.txt не выводим
    call ErrorBox, offset sOpenError, si
    GFRet:
    ret
    GFReadError:
    pop ds
    call ErrorBox, offset sReadError, si
    jmp FNCloseFile
    GFSizeError:
    ;поместим в начало байт 0 и сбросим длину в 0
    mov byte ptr ds:[0],0
    pop ds
    mov FileLen, 0
    call ErrorBox, offset sSizeError, si
    jmp FNCloseFile
    GetFile endp

    ;запись файла
    SetFile proc
    lea dx, FName
    cmp FName, 0
    jnz SFOpen
    lea dx, default
    SFOpen:
    mov si, dx ;сохраним имя (для сообщений)
    mov ah, 3ch ;создаем файл (если был с таким именем, то тот потер яется)
    xor cx, cx
    int 21h
    jc SFCreateError
    mov bx, ax ;описатель файла
    mov cx, FileLen ;длина файла
    push ds
    mov ds, FileSeg
    xor dx, dx
    mov ah, 40h ;пишем в файл с адреса ds:dx
    int 21h
    pop ds
    jc SFWriteError

    mov fChange, 0 ;сбросим флаг изменения
    SFCloseFile:
    mov ah, 3eh
    int 21h ;закрываем файл
    ret
    ;сообщения об ошибках
    SFCreateError:
    call ErrorBox, offset sCreateError, si
    SFRet:
    ret
    SFWriteError:
    call ErrorBox, offset sWriteError, si
    jmp SFCloseFile
    SetFile endp

    ;сообщение об ошибке (всегда две внутренние строки)
    ;sFormat - форматная строка, параметром можно указать %, в то место вставится sStr
    ;sStr - имя файла, вставляемое, как параметр в сообщение
    ;во второй строке всегда пишем: "Нажмите на любую клавишу"
    ErrorBox proc sFormat:word, sStr:word
    local sTextBuffer:byte:76, \ ;буфер для формирования строки
    wSave:word:80*4, \ ;для сохран ения старого содержимого экрана
    MB_x1:word, MB_y1:word, MB_x2:word, MB_y2:word ;координаты окна (псевдографики)

    ;посчитаем размеры окна, для этого найдем максимальную длину строки
    xor dx, dx ;максимальная длина
    mov si, sFormat ;форматная строка
    lea di, sTextBuffer ;где формируем данные для вывода
    xor cx, cx ;длина первой строки
    EBForm:
    lodsb
    cmp al, 0
    je EBSecond ;добавляем вторую строку
    cmp al, '%'
    je EBParm ;добавляем параметр
    mov [di], al ;сохраняем
    inc di
    cmp al, ' ' ;0dh,0ah не считаем
    jb EBForm
    inc cx ;считаем символы
    jmp EBForm
    EBParm: ;копируем параметр
    push si
    mov si, sStr
    EBParmLoop:
    lodsb
    cmp al, 0
    je EBParmEnd
    inc cx ;считаем длину строки
    mov [di], al
    inc di
    jmp EBParmLoop
    EBParmEnd:
    pop si
    jmp EBForm ;продолжаем проссматривать форматную строку
    EBSecond:
    cmp cx, dx ;сравниваем с максимумом
    jbe EBAnyKe y
    mov dx, cx
    EBAnyKey: ;добавляем строку sAnyKey
    xor cx, cx
    lea si, sAnyKey
    EBAnyLoop:
    lodsb
    cmp al, 0
    je EBCalcSize ;конец
    mov [di], al
    inc di
    cmp al, ' '
    jb EBAnyLoop
    inc cx ;считаем
    jmp EBAnyLoop
    EBCalcSize:
    cmp cx, dx ;ищем максимум
    ja EBCalcMiddle
    mov cx, dx
    EBCalcMiddle:
    add cx, 4 ;+ по пробелу и чертечке слева и справа
    mov ax, XSize ;сделаем, чтобы окно было посередине экрана
    sub ax, cx
    shr ax, 1
    mov MB_x1, ax ;Х левого верхнего угла
    add ax, cx
    dec ax
    mov MB_x2, ax ;Х правого нижнего угла
    mov ax, YSize
    sub ax, 4
    shr ax, 1
    mov MB_y1, ax ;Y левого верхнего угла
    add ax, 3 ;внутри 2 строки
    mov MB_y2, ax ;Y правого нижнего угла

    lea di, wSave ;сохраняем старое содержимое экрана
    mov cx, XSize ; причем для простоты сохраняем строки от начала до конца
    mov ax, MB_y1
    mul cx
    shl ax, 1
    mov si, ax
    shl cx, 2
    push ds
    push es
    push ds
    push es
    pop ds
    pop es
    rep movsw
    pop es
    pop ds

    ;рисуем окно с рамкой с цвет ом ошибок
    call PrWin, MB_x1, MB_y1, MB_x2, MB_y2, SINGLE, ErrorColor
    ;и выводим текст из 2-х строк в позицию (1,1)
    mov ax, MB_x1
    inc ax
    inc ax
    mov cx, MB_y1
    inc cx
    mov dx, MB_x2
    sub dx, ax
    lea bx, sTextBuffer
    call PrText, ax, cx, dx, 2, bx

    push word ptr XScreen ;сохраняем позицию курсора
    mov ax, MB_x2 ;установим курсор в конец второй строки
    sub al, 2
    mov XScreen, al
    mov ax, MB_y2
    sub al, 2
    mov YScreen, al
    call SetCursor

    mov ah, 0 ;ждем нажатие на клавишу
    int 16h

    lea si, wSave ;востановим экран
    mov cx, XSize
    mov ax, MB_y1
    mul cx
    shl ax, 1
    mov di, ax
    shl cx, 2
    rep movsw

    pop word ptr XScreen ;восстановим курсор
    call SetCursor
    ret
    ErrorBox endp

    ;вывод сообщения с получением кода нажатой клавиши
    ;sStr - выводимое сообщение
    ;nRows - число информационных строк
    MessageBox proc sStr:word, nRows:word
    local wSave:word:8 0*14, \;для сохранения старого содержимого (максимум 12 инфо строк)
    MB_x1:word, MB_y1:word, MB_x2:word, MB_y2:word ;координаты окна

    ;найдем максимальную длину строки
    mov si, sStr
    xor cx, cx ;текущая
    mov dx, cx ;максимальная
    MBStrLen:
    lodsb
    cmp al, 0ah
    je MB_EOL
    cmp al, 0
    je MBCmpLastPart
    cmp al, ' '
    jb MBStrLen
    inc cx
    jmp MBStrLen
    MB_EOL:
    cmp cx, dx
    jbe to_MBStrLen
    mov dx, cx
    to_MBStrLen:
    xor cx, cx
    jmp MBStrLen
    MBCmpLastPart:
    cmp cx, dx
    ja MBCalcMiddle
    mov cx, dx
    MBCalcMiddle: ;посчитаем Xи Y, чтобы было в центре экрана
    add cx, 4 ;добавим два пробела и две черточки
    mov ax, XSize
    sub ax, cx
    shr ax, 1
    mov MB_x1, ax ;Х левого верхнего угла
    add ax, cx
    dec ax
    mov MB_x2, ax ;Х правого нижнего угла
    mov ax, YSize
    sub ax, nRows ;инфо строки
    sub ax, 2 ;верхняя и нижняя
    shr ax, 1
    mov MB_y1, ax ;Y левого верхнего уг ла
    add ax, nRows
    inc ax
    mov MB_y2, ax ;Y правого нижнего угла

    lea di, wSave ;сохраним экран
    mov cx, XSize
    inc cx
    mov ax, MB_y1
    mul cx
    shl ax, 1
    mov si, ax
    mov ax, nRows
    add ax, 2
    mul cx
    mov cx, ax
    push ds
    push es
    push ds
    push es
    pop ds
    pop es
    rep movsw
    pop es
    pop ds

    ;нарисуем окно с рамкой
    call PrWin, MB_x1, MB_y1, MB_x2, MB_y2, SINGLE, MessageColor
    ;выведем текст в позицию (2,1)
    mov ax, MB_x1
    inc ax
    inc ax
    mov cx, MB_y1
    inc cx
    mov dx, MB_x2
    sub dx, ax
    call PrText, ax, cx, dx, nRows, sStr

    push word ptr XScreen ;сохраним курсор
    mov ax, MB_x2 ;курсор в конец последней инфо строки
    sub al, 2
    mov XScreen, al
    mov ax, MB_y2
    sub al, 2
    mov YScreen, al
    call SetCursor

    mov ah, 0
    int 16h ;ждем

    push ax ;сохраним код!
    lea si, wSave ;востановим старое содержимое экрана
    mov cx, XSiz e
    inc cx
    mov ax, MB_y1
    mul cx
    shl ax, 1
    mov di, ax
    mov ax, nRows
    add ax, 2
    mul cx
    mov cx, ax
    rep movsw
    pop ax ;восстановим и вернем код нажатой клавиши!

    pop word ptr XScreen ;восстановим позицию курсора
    ret ;установится в сновном цикле!
    MessageBox endp

    ;вывод сообщения и запрос имени файла
    ;sTitle - первая строка сообщения
    ;sName - строка "Имя файла:"
    ;sOldName - адрес строки со старым именем и куда будет это имя потом записано
    NameBox proc sTitle:word, sName:word, sOldName:word
    local sTextBuffer:byte:76, \;для формирования строки для вывода
    wSave:word:80*4, \;для сохранения экрана
    MB_x1:word, MB_y1:word, MB_x2:word, MB_y2:word ;позиция окна
    local offName:word, \;смещение вводимого имени в строке sTextBuffer
    lenName:word, \;длина собственно имени файла
    lenStr:word ;длина строки sName

    xor dx, dx ;ищем максимальную длину строки
    mov si, sTitle ; начинаем с первой
    lea di, sTextBuffer ;и формируем строку в sTextBuffer
    xor cx, cx
    NBForm:
    lodsb
    cmp al, 0
    je NBAdd Name
    mov [di], al
    inc di
    cmp al, ' '
    jb NBForm
    inc cx
    jmp NBForm
    NBAddName: ;добавляем sName
    mov dx, cx
    xor cx, cx
    mov lenStr, cx ;считаем ее длину
    mov si, sName
    NBNameLoop:
    lodsb
    cmp al, 0
    je NBOldName
    mov [di], al
    inc di
    cmp al, ' '
    jb NBNameLoop
    inc cx
    inc lenStr
    jmp NBNameLoop
    NBOldName:
    add cx, 12 ;12 позиций на имя 8.3 !

    mov offName, di ;начало имени файла
    mov lenName, 0 ;длина имени

    mov si, sOldName ;перенесем старое имя
    cmp byte ptr [si], 0
    jne NBCopyName
    lea si, Default
    NBCopyName:
    lodsb
    cmp al, 0
    je NBCalcSize
    mov [di], al
    inc di
    inc lenName
    jmp NBCopyName
    NBCalcSize:
    mov [di], al ;закрываем нулем

    cmp cx, dx
    ja NBCalcMiddle
    mov cx, dx ;максимальная длина
    NBCalcMiddle:
    add cx, 4 ;+ 2 пробела и 2 черточки
    mov ax, XSize ;посреди экрана
    sub ax, cx
    shr ax, 1
    mov MB_x1, ax
    add ax, cx
    dec ax
    mov MB_x2, ax
    mov ax, YSize
    sub ax, 4
    shr ax, 1
    mov MB_y1, ax
    add ax, 3
    mov MB_y2, ax

    lea di, wSave ;сохраняем старый экран
    mov cx, XSize
    inc cx
    mov ax, MB_y1
    mul cx
    shl ax, 1
    mov si, ax
    shl cx, 2
    push ds
    push es
    push ds
    push es
    pop ds
    pop es
    rep movsw
    pop es
    pop ds

    push word ptr XScreen;сохраняем курсор

    mov ax, MB_x1 ;курсор на конец имени файла
    add ax, lenStr
    add ax, lenName
    inc al
    mov XScreen, al
    mov ax, MB_y2
    sub al, 2
    mov YScreen, al ;во второй строке

    ;нарисуем окно с рамкой
    call PrWin, MB_x1, MB_y1, MB_x2, MB_y2, SINGLE, MessageColor

    mov si, offName ;адрес имени
    mov bx, lenName ;длина имени, одновременно индекс конца введенной строки

    NBPrName: ;цикл ввода строки имени файла
    push si bx ;сохраним используемые регистры
    ;выводим текст вместе с вв одимым именем
    mov ax, MB_x1
    inc ax
    inc ax
    mov cx, MB_y1
    inc cx
    mov dx, MB_x2
    sub dx, ax
    lea di, sTextBuffer
    call PrText, ax, cx, dx, 2, di

    call SetCursor ;установка курсора
    pop bx si

    NBKeyLoop: ;цикл ожидания нажатия на клавишу
    mov ah, 0
    int 16h
    cmp ah, 1
    je NBEscape ;Escape - выходим без сохранения
    cmp al, 0dh
    je NBEnter ;Enter - сохраняем имя
    cmp al, 8
    je NBBackSpace ;BackSpace - удаляем последний символ
    cmp al, ' '
    jbe NBKeyLoop ;управляющие игнорируем
    cmp bx, 12
    jae NBKeyLoop ;максимум 12 символов
    mov [bx+si], al ;сохраняем
    inc bx ;инкремент
    mov byte ptr[bx+si], 0 ;закрываем нулем
    inc XScreen ;инкремент позиции на экране
    jmp NBPrName ;заново отрисовываем

    NBBackSpace: ;BackSpace
    test bx, bx
    jz NBKeyLoop ;в начале - игнорируем
    dec bx ;уменьшаем индекс
    mov byte ptr[bx+si], 0 ;признак конца
    dec XScreen ;декре мент позиции на экране
    jmp NBPrName ;заново отрисовываем
    NBEscape: ;Escape - выходим без сохранения
    mov di, 1 ;чтобы в бите D0 была единица
    jmp NBReturn
    NBEnter:
    mov di, sOldName ;копируем имя по указанному адресу
    mov cx, bx ;длина
    inc cx ;+ 0
    push es
    push ds
    pop es
    rep movsb
    pop es
    xor di, di ;D0 = 0
    NBReturn:
    push di ;сохраним признак
    lea si, wSave ;восстановим экран
    mov cx, XSize
    inc cx
    mov ax, MB_y1
    mul cx
    shl ax, 1
    mov di, ax
    shl cx, 2
    rep movsw
    pop di

    pop word ptr XScreen ;востановим позицию курсора
    call SetCursor

    shr di, 1 ;бит D0 в бит С - признак, как вышли!
    ret
    NameBox endp

    ;вывод текста
    ;PT_x1, PT_y1 - координаты начала вывода
    ;PT_xcount - мах число символов по Х
    ;PT_ycount - число инфо строк
    ;PT_str - адрес строки, заканчивающейся 0, для перехода на другую строку 0dh,0ah
    PrText proc uses di, PT_x1:word, PT_ y1:word, PT_xcount:word, PT_ycount:word, PT_str:word
    ;вычисляем смещение в сегменте видеоданных
    mov ax, ss:XSize
    inc ax
    mul PT_y1
    add ax, PT_x1
    shl ax, 1
    mov di, ax

    mov si, PT_str ;адрес строки
    mov dx, di ;начало строки на экране, для подсчета адреса следующей строки
    mov cx, PT_xcount ;число колонок
    mov bx, PT_ycount ;число строк
    PTRLoop:
    test bx, bx ;кончилось?
    jz to_PrRet
    PTCLoop:
    jcxz PrNextRow ;дошли до конца строки - переход на следующую строку
    lodsb
    cmp al, 0 ;дошли до конца строки?
    jnz PTCmp0d ;нет, на проверку 0dh
    jcxz to_PrRet ;заполним до конца пробелами
    mov al, ' '
    PTEndRow_loop:
    stosb
    inc di
    loop PTEndRow_loop
    ;также заполним пробелами всю следующую строку
    cmp PT_ycount, 23 ;но только для всего экрана, для сообщений - игнорируем
    jbe PrRet
    cmp si, 2 ;для пустого файла - игнорируем
    jb PrRet
    cmp byte ptr [si-2], 0ah ;если последний символ 0ah - игнорируем,
    je PrRet ; для него уже очищено до конца!
    mov di, dx ;адрес следующей строки
    add di, ss:XSize
    a dd di, ss:XSize
    inc di
    inc di
    mov dx, di
    dec bx
    mov cx, PT_xcount ;"опробелим"
    PTEndRow_loop_2:
    stosb
    inc di
    loop PTEndRow_loop_2
    to_PrRet:
    jmp PrRet
    PTCmp0d: ;анализируем дальше
    cmp al, 0dh
    jz PTCLoop ;0dh игнорируем
    cmp al, 0ah
    jz PrNextRow ;по 0ah переходим на новую строку
    cmp al, 9
    jne PTstosb ;обычный символ проосто выводим
    mov ax, di ;табуляцию расширяем до позиции, кратной 8
    sub ax, dx
    shr ax, 1
    and ax, 7
    sub ax, 7
    neg ax
    mov ah, al ;ah - число дополнительных пробелов
    mov al, ' '
    PTExpandTabLoop:
    jcxz PrNextRow ;дошли ли до края строки на экране
    cmp ah, 0
    je PTstosb ;на вывод еще одного пробела
    stosb
    inc di
    dec cx ;счетчик символов, которые еще можно вывести
    dec ah ;счетчик дополнительных пробелов для расширения табуляции
    jnz PTExpandTabLoop
    PTstosb:
    stosb ;вывод символа
    inc di ;обойдем атрибут
    dec cx ;декремент счетчика
    jmp PTCLoop ;на следующий
    PrNextRow: ;переход на следующую строку
    jcxz PrNextRow_1 ;сначала дополним до конца пробелами
    mov al, ' '
    PrEndRow_loop:
    stosb
    inc di
    loop PrEndRow_loop
    PrNextRow_1:
    mov di, dx ;адрес следующей строки
    add di, ss:XSize
    add di, ss:XSize
    inc di
    inc di
    mov dx, di
    dec bx ;счетчик строк
    mov cx, PT_xcount ;заново счетчик колонок
    ;PTSearchLineEndLoop:
    ; cmp al, 0ah
    ; je PTRLoop
    ; lodsb
    ; cmp al, 0
    ; je PrRet
    ; jmp PTSearchLineEndLoop
    jmp PTRLoop ;на повтор
    PrRet:
    ret ;все выведено!
    PrText endp

    ;вывод в последней строке "F1 - помощь"
    PrHelpMess proc
    mov ax, YSize
    inc ax
    mov di, XSize
    inc di
    mul di
    sub ax, sMessHelpLen ;длина строки
    shl ax, 1
    mov di, ax ;адрес, куда выводим
    lea si, sMessHelp ;строка
    PrHelp_loop:
    lodsb
    cmp al, 0
    je PrHelRet
    stosb
    inc di
    loop PrHelp_loop
    PrHelRet:
    ret
    PrHelpMess endp

    ;выход
    exit proc
    cmp fChange, 0 ;было ли изменение?
    je EContinue
    ;1 строку сообщения
    call MessageBox, offset sChanged, 1
    ;возвращается скан-код нажатой клавиши
    cmp ah, 15h ;Y?
    je EContinue ;Y - выходим
    jmp NewCursor ;восстановим курсор и продолжаем работать
    EContinue:
    lea si, SaveScr ;восстановим эвесь экран
    xor di, di
    mov ax, XSize
    mov cx, YSize
    inc ax
    inc cx
    mul cx
    inc ax
    mov cx, ax
    rep movsw

    mov ah, 2 ;восстановим курсор
    mov bh, 0
    mov dx, PosOld
    int 10h
    mov ax, 4c00h ;выход в ДОС
    int 21h
    exit endp

    ;индексы в массиве псевдографики
    LU equ 0
    RU equ 1
    RD equ 2
    LD equ 3
    HH equ 4
    VV equ 5

    ;индексы в массиве адресов псевдографики
    SINGLE equ 0
    DOUBLE equ 1

    ;сегмент данных
    .data
    ;краткая помощь по F1
    sHelp db 'F1 - эта помощь' ;, 0dh, 0ah
    db 'F2 - запись файла', 0dh, 0ah
    db 'F3 - чтение файла', 0dh, 0ah
    db 1ah,' - курсор вправо ', 0dh, 0ah
    db 1bh,' - курсор влево', 0dh, 0ah
    db 18h,' - курсор вверх', 0dh, 0ah
    db 19h,' - курсор вниз', 0dh, 0ah
    db 'BSp- удалить символ слева', 0dh, 0ah
    db 'Tab- вставить табуляцию', 0dh, 0ah
    db 'Ent- перейти на новую строку', 0dh, 0ah
    db 'Esc- выход', 0
    ;подсказка о помощи в последней строке
    sMessHelp db ' F1-помощь ',0
    ;длина подсказки
    sMessHelpLen equ $-sMessHelp
    ;сообщение, добавляемое в сообщения об ошибках
    sAnyKey db 0dh,0ah,'Нажмите на любую клавишу',0
    ;сообщения об ошибках
    sOpenError db 'Файл % не найден',0
    sReadError db 'Ошибка чтения файла %',0
    sSizeError db 'Длина файла % >= 65535',0
    sCreateError db 'Ошибка создания файла %',0
    sWriteError db 'Ошибка записи файла %',0
    ;для запроса имени файла
    sFileName db 'Имя файла: ',0
    sReadFile db 'Чтение файла' ;, 0dh, 0ah, 0
    sWriteFile db 'Запись файла', 0dh, 0ah, 0
    ;для подтверждения продолжения при изменении файла
    sChanged db 'Файл изменен, продолжать? (Y,N)',0
    ;таблицы псевдографики
    Borders dw BorderSingle, BorderDouble
    BorderSingle db 0dah,0bfh,0d9h,0c0h,0c4h,0b3h
    BorderDouble db 0c9h,0bbh,0bch,0c8h,0cdh,0bah
    ;имя файла по-умолчанию
    Default db 'Noname.txt',0
    ;цвета (атрибуты) окон в виде: ст байт - текст внутри, мл байт - рамка
    ;цвет основного окна
    MainColor dw 1f17h
    ;цвет сообщения об ошибке
    ErrorColor dw 4f47h
    ;цвет сообщения, например, ввода имени файла
    MessageColor dw 3f37h
    ;таблица отрабатываемых кодов (скан-кодов)
    KeyTable db 01h,48h,4bh,4dh,50h,3bh,3dh,3ch,0eh,0fh,1ch
    ;длина KeyTable
    KeyTablelen equ $-KeyTable
    ;соответствующая таблица подпрограмм отработки
    PrgTable dw Exit,KeyUp,KeyLeft,KeyRight
    dw KeyDown,KeyHelp,KeyRead,KeyWrite
    dw KeyBack,KeyInsert,KeyEnter

    . data?
    Xsize dw ? ;размер экрана в колонках-1, т.е. индекс последней колонки на экране
    Ysize dw ? ;размер экрана в строках-1, т.е. индекс последней строки на экране
    FileSeg dw ? ;сегмент данных файла
    FileLen dw ? ;длина данных файла
    UpLine dw ? ;смещение в сегменте данных файла первой строки отображения на экране
    CurLine dw ? ;смещение в сегменте данных файла текущей строки
    PosOld dw ? ;сохраненная позиция курсора
    XScreen db ? ;текущая позиция по Х на экране
    YScreen db ? ;текущая позиция по Y на экране
    XFile db ? ;текущая позиция по Х в текущей строке в файле
    YFile db ? ;текущая позиция по Y в текущей строке в файле
    fChange db ? ;флаг изменеия содержимого файла
    FName db 128 dup (?) ;буфер для имени файла
    SaveScr label word ;буфер для сохранения содержимого экрана текущей страницы

    end

    В ASCII-кодировке текст можно взять здесь
    -----
    Удачи!

    Ответ отправил: Лысков Игорь Витальевич, Модератор
    Ответ отправлен: 20.05.2010, 00:59
    Номер ответа: 261516
    Украина, Кировоград
    Тел.: +380957525051
    ICQ # 234137952
    Mail.ru-агент: igorlyskov@mail.ru
    Абонент Skype: igorlyskov

    Оценка ответа: 5

    Вам помог ответ? Пожалуйста, поблагодарите эксперта за это!
    Как сказать этому эксперту "спасибо"?
  • Отправить SMS #thank 261516 на номер 1151 (Россия) | Еще номера »
  • Отправить WebMoney:

  • Оценить выпуск »
    Нам очень важно Ваше мнение об этом выпуске рассылки!

    Задать вопрос экспертам этой рассылки »

    Скажите "спасибо" эксперту, который помог Вам!

    Отправьте СМС-сообщение с тестом #thank НОМЕР_ОТВЕТА
    на короткий номер 1151 (Россия)

    Номер ответа и конкретный текст СМС указан внизу каждого ответа.

    Полный список номеров »

    * Стоимость одного СМС-сообщения от 7.15 руб. и зависит от оператора сотовой связи. (полный список тарифов)
    ** При ошибочном вводе номера ответа или текста #thank услуга считается оказанной, денежные средства не возвращаются.
    *** Сумма выплаты эксперту-автору ответа расчитывается из суммы перечислений на портал от биллинговой компании.


    © 2001-2010, Портал RFpro.ru, Россия
    Авторское право: ООО "Мастер-Эксперт Про"
    Автор: Калашников О.А. | Программирование: Гладенюк А.Г.
    Хостинг: Компания "Московский хостер"
    Версия системы: 2010.6.15 от 25.05.2010

    В избранное