nixp.ru v3.0

19 октября 2017,
четверг,
12:07:51 MSK

DevOps с компанией «Флант»
NyaO написал 10 мая 2008 года в 20:36 (734 просмотра) Ведет себя неопределенно; открыл 1 тему в форуме, оставил 3 комментария на сайте.

Вообщем задали такую прогу.

Реализовать программу, ежесекундно выводящую в правом углу экрана системное время «чч:мм:сс»

Есть из примеров исходничек проги которая:

; В бесконечном цикле выводит на экран строку первый символ строки заменяется

; на символ, нажатый на клавиатуре. При этом циклически изменяет цвет (атрибуты)

; строки от 1 до 15 один раз в секунду (приблизительно 18 тиков системного таймера).

; При нажатии клавиши «0» выходит из программы.

.model small

datasg segment

old_cs dw ? ; для хранения «старого» вектора

old_ip dw ? ; прерываний с номером 1Ch

tick dw 0 ; счетчик тиков системного таймера

atr db 14 ; изначальный атрибут символов (желтый)

msg db 'X-Y’; строка, выводимая на экран

MSG_LEN equ $-msg ; динна строки

T_MAX equ 18; задаем константу для интервала изменения атрибута (в тиках)

; строка и столбец, начиная с которых будет выводиться символы

POS_Y equ 14

POS_X equ 40

datasg ends

stacksg segment stack

db 256 dup(?)

stacksg ends

codesg segment

assume cs:codesg, ds:datasg, ss:stacksg

; подпрограмма обработки прерываний 1Ch

new_1c proc far

; обработчик прерывания 1Ch -> сохраняем значения всех изменяемых регистров

push ax

push bx

push ds

push es

; настраиваем ds на наш сегмент данных

mov ax, datasg

mov ds, ax

inc tick ; увеличиваем счетчик тиков

; проверка буфера клавиатуры

mov ax, 40h ; настраиваем es на сегмент области данных BIOS

mov es, ax

mov ax, es:[1Ch] ; в ax указатель «хвоста» буфера клавиатуры

mov bx, es:[1Ah] ; в bx указатель «головы»

cmp bx, ax ; буфер пуст ?

jne save_sym ; нет — идем сохранять символ

; да — выходим из обработчика

jmp back

save_sym:

mov al, es:[bx] ; извлечь символ из буфера

; укажем, что символ обработан — поместим указатель «хвоста» в «голову»

mov es:[1Ch], bx

; сохраняем введенный символ в начало строки

mov msg[0], al

back:

pop es

pop ds

pop bx

pop ax

iret

new_1c endp

; основная программа

start:

mov ax, datasg

mov ds, ax

; чтение текущего вектора прерывания 1Ch

mov ah, 35h ; функция получения вектора

mov al, 1Ch ; номер вектора

int 21h

; возвращает сегмент — в es, смещение в bx

; сохраним полученный адрес обработчика

mov old_ip, bx

mov old_cs, es

; установим новый обработчик прерывания 1c

push ds

; в ds:dx — адрес нового обработчика прерывания

mov dx, offset new_1c

mov ax, seg new_1c

mov ds, ax

mov ah, 25h

mov al, 1Ch

int 21h

pop ds

; настроим es на наш сегмент данных

mov ax, datasg

mov es, ax

; основной цикл программы

main_loop:

; проверка завершение работы

cmp msg[0], 30h ; нажата ли клавиша «0» ?

je quit ; если да — конец программы

; проверка прошедшего времени

cmp tick, T_MAX ; проверяем прошло ли T_MAX тиков

jl check_for_changes ; еще нет -> идем проверять изменение выводимого символа

; уже прошло -> сбрасываем счетчик тиков

mov tick, 0

; и меняем цвет

mov al, atr

inc al

; если больше 15 -> оборачиваем атрибут

cmp al, 15

jle save_attr

mov al, 1

save_attr:

mov atr, al ; сохраняем атрибут

jmp show_msg ; идем перерисовывать строку

check_for_changes:

; проверяем был ли изменен первый символ выводимой строки

cmp bh, msg; сравниваем предыдущий первый символ строки (хранится в bh) с текущим

je main_loop ; нет изменений -> в начало цикла

show_msg:

xor bh, bh ; обнулим bh для предотвращения ошибки

; выводим строку с заданным атрибутом

mov ah, 13h

mov al, 0 ; режим вывода

; строка и столбец, начиная с которых будет выводиться строки

mov dh, POS_Y

mov dl, POS_Y

lea bp, msg ; в ES:BP — адрес начала строки в памяти

mov bl, atr ; атрибут, если строка содержит только символы

mov cx, MSG_LEN ; длина строки

int 10h

; сохраним в bh текущий первый символ для проверки

; необходимости повторного вывода строки

mov bh, msg[0]

jmp main_loop

quit:

; восстановление старого вектора обработчика прерывания 1Ch

push ds

; в ds:dx — адрес исходного обработчика прерывания 1Ch

mov dx, old_ip

mov ax, old_cs

mov ds, ax

mov ah, 25h ; функция установки вектора

mov al, 1Ch ; номер вектора

int 21h

pop ds

; завершение работы программы

mov ax, 4C00h

int 21h

codesg ends

end start

Мне нужно из неё получить ту прогу которую задали. Насколько я знаю необходимо использовать прерывание int 1Ah. Или int 21h Но я незнаю как оно работает и из каких регистров считать время. Т.е. часы, минуты и секунды. Как я понимаю надо в учаток кода вставить код с получением этого времени. Но вот в какое место именно в коде. Я вообще когда пробовал я пытался записать значения в msg. Типо mov [msg],al. Но ничего не получилось 8( Ребята, помогите реализовать прогу. Или разьясните как реализовать самому, буду презнателен за любой ответ. 8) Просто сложность заключается в том, что надо как-то код, насколько я понимаю реализовать с помошью процедуры new_1ch.

Ещё не совсем понятен вот этот кусочек из примерчика:

mov ax, 40h ; настраиваем es на сегмент области данных BIOS

mov es, ax

mov ax, es:[1Ch] ; в ax указатель «хвоста» буфера клавиатуры

mov bx, es:[1Ah] ; в bx указатель «головы»

cmp bx, ax ; буфер пуст ?

jne save_sym ; нет — идем сохранять символ

; да — выходим из обработчика

jmp back

save_sym:

mov al, es:[bx] ; извлечь символ из буфера

; укажем, что символ обработан — поместим указатель «хвоста» в «голову»

mov es:[1Ch], bx

Что он в точности делает?

Помогите пожалуйста, очень надо!!!! 8)

Anarchist

Разжевать и в рот положить?

NyaO

Да.. 8)

rgo

Возьми книжку про асм под дос, там всё это подробно описано. Или ты ждёшь, что я достану книжку с полки, и начну здесь на форуме опубликовывать главами?

NyaO

Не злись, я ж просто просил пояснить кусочек. 8)))

myst

Отформатировал бы сначала по-людски что ли…

NyaO

Это не мой текст 8) С книжки взят.. 8)