Часовой пояс: UTC + 3 часа




Начать новую тему Новая тема / Ответить на тему Ответить  Сообщений: 7 
  Пред. тема | След. тема 
В случае проблем с отображением форума, отключите блокировщик рекламы
Автор Сообщение
 

Member
Статус: Не в сети
Регистрация: 04.02.2003
Откуда: Москва
Тут такое дело, друг, зная, что я учусь на программера, попросил помочь с одной прогой. Я в асме полный ноль - не проходили ещё, а друга выручать надо. Помогите, очень прошу!
Задача такая - есть уже написанные резидентные часы, нужно сделать:
1)чтобы они находились в нижнем правом углу экрана и были белые символы на чёрном фоне;
2)самое главное - впихнуть в них проверку на повторный запуск;
3)желательно, но не обязательно - они не работают под ХР, им нужен нормальный ДОС, это тоже можно исправить.
Вот листинг:
Код:
; Компиляция:
; TASM:
;  tasm /m timer.asm
;  tlink /t /x timer.obj
; MASM:
;  ml /c timer.asm
;  link timer.obj,,NUL,,,
;  exe2bin timer.exe timer.com
; WASM:
;  wasm timer.asm
;  wlink file timer.obj form DOS COM
;


   .model   tiny
   .code
   .186         ; для pusha/popa и сдвигов
   org   100h
start   proc   near
; сохранить адрес предыдущего обработчика прерывания 1Ch
   mov   ax,351Ch   ; AH = 35h, AL = номер прерывания
   int   21h      ; функция DOS: определить адрес обработчика
   mov   word ptr old_int1Ch,bx      ; прерывания
   mov   word ptr old_int1Ch+2,es   ; (возвращается в ES:BX)
; установить наш обработчик
   mov   ax,251Ch   ; AH = 25h, AL = номер прерывания
   mov   dx,offset int1Ch_handler ; DS:DX - адрес обработчика
   int   21h      ; установить обработчик прерывания 1Ch

; здесь размещается собственно программа, например вызов command.com
   mov   ah,1
   int   21h      ; ожидание нажатия на любую клавишу
; конец программы

; восстановить предыдущий обработчик прерывания 1Сh
   mov   ax,251Ch      ; AH = 25h, AL = номер прерывания
   mov   dx,word ptr old_int1Ch+2
   mov   ds,dx
   mov   dx,word ptr cs:old_int1Ch ; DS:DX - адрес обработчика
   int   21h

   ret

old_int1Ch dd   ? ; здесь хранится адрес предыдущего обработчика
start_position   dw 0   ; позиция на экране, в которую выводится текущее
         ; время
start   endp

; обработчик для прерывания 1Ch
; выводит текущее время в позицию start_position на экране (только в текстовом
; режиме)

int1Ch_handler   proc   far
   pusha      ; обработчик аппаратного прерывания
   push   es   ; должен сохранять ВСЕ регистры
   push   ds

   push   cs   ; на входе в обработчик известно только значение
   pop   ds   ; регистра CS
   mov   ah,02h   ; Функция 02h прерывания 1Ah:
   int   1Ah      ; чтение времени из RTC
   jc   exit_handler ; если часы заняты - в другой раз

; AL = час в BCD-формате
   call   bcd2asc   ; преобразовать в ASCII
   mov   byte ptr output_line[2],ah ; поместить их в
   mov   byte ptr output_line[4],al ; строку output_line

   mov   al,cl      ; CL = минута в BCD-формате
   call   bcd2asc
   mov   byte ptr output_line[10],ah
   mov   byte ptr output_line[12],al

   mov   al,dh      ; DH = секунда в BCD-формате
   call   bcd2asc
   mov   byte ptr output_line[16],ah
   mov   byte ptr output_line[18],al

   mov   cx,output_line_l   ; число байтов в строке - в CX
   push   0B800h
   pop   es         ; адрес в видеопамяти
   mov   di,word ptr start_position ; в ES:DI
   mov   si,offset output_line ; адрес строки в DS:SI
   cld
   rep movsb         ; скопировать строку
exit_handler:
   pop   ds      ; восстановить все регистры
   pop   es
   popa
   jmp   cs:old_int1Ch ; передать управление предыдущему
            ; обработчику

; процедура bcd2asc
; преобразует старшую цифру упакованного BCD-числа в AL в ASCII-символ в AH,
; а младшую цифру - в ASCII-символ в AL
bcd2asc      proc   near
   mov   ah,al
   and   al,0Fh   ; оставить младшие 4 бита в AL
   shr   ah,4      ; сдвинуть старшие 4 бита в AH
   or   ax,3030h   ; преобразовать в ASCII-символы
   ret
bcd2asc      endp

; строка " 00h 00:00" с атрибутом 1Fh (белый на синем) после каждого символа
output_line   db   ' ',e7h,'0',e7h,'0',e7h,':',e7h
      db   ' ',e7h,'0',e7h,'0',e7h,':',e7h
      db   '0',e7h,'0',e7h,' ',e7h
output_line_l   equ $-output_line

int1Ch_handler   endp

end start

Помогите, хлопцы!

_________________
Каждый человек по-своему прав. А по-моему, нет.



Партнер
 

Member
Статус: Не в сети
Регистрация: 12.03.2003
Откуда: Израиль
Гхм! Переписывать лень, но...

Белый на черном - там внизу строчка output_line. Меняешь e7 на f7.
Повторный запуск - там, где берут предыдущий адрес обработчика прерывания (351С), сравнивать смещение (полученное в bx) со смещением процедуры (int1Ch_handler)
XP - не вижу никаких объективных причин не работать.

А! Про нижний угол!
Балуемся со значением start_position.
Только не советую вешать туда часы: при прокрутке ДОСовского окна они размажутся на весь экран.

_________________
Более мощный компьютер глючит быстрее и точнее.


 

Member
Статус: Не в сети
Регистрация: 04.02.2003
Откуда: Москва
WhPh
Цитата:
Повторный запуск - там, где берут предыдущий адрес обработчика прерывания (351С), сравнивать смещение (полученное в bx) со смещением процедуры (int1Ch_handler)

Ээээ... Понимаешь, я асм не знаю вообще! А это самое главное, что нужно сделать. А разбираться особо некогда - у самого сессия.
Цитата:
XP - не вижу никаких объективных причин не работать.
Он запускал, говорит, не пашет. Только под 98 ему удалось его запустить...
Цитата:
Балуемся со значением start_position.
Только не советую вешать туда часы: при прокрутке ДОСовского окна они размажутся на весь экран.
Какие значения может принимать, какие позиции "безопасные", есть ли какая-то табличка соответствия значения и положения часов?

_________________
Каждый человек по-своему прав. А по-моему, нет.


 

Member
Статус: Не в сети
Регистрация: 12.03.2003
Откуда: Израиль
Получи! Честно предупреждаю, что не компилировал и не проверял!

Код:
; Компиляция:
; TASM:
;  tasm /m timer.asm
;  tlink /t /x timer.obj
; MASM:
;  ml /c timer.asm
;  link timer.obj,,NUL,,,
;  exe2bin timer.exe timer.com
; WASM:
;  wasm timer.asm
;  wlink file timer.obj form DOS COM
;


   .model   tiny
   .code
   .186         ; для pusha/popa и сдвигов
   org   100h
start   proc   near
; сохранить адрес предыдущего обработчика прерывания 1Ch
   mov   ax,351Ch   ; AH = 35h, AL = номер прерывания
   int   21h      ; функция DOS: определить адрес обработчика
   mov   word ptr old_int1Ch,bx      ; прерывания
   mov   word ptr old_int1Ch+2,es   ; (возвращается в ES:BX)

   cmp   bx, offset int1Ch_handler
   jz    bailout   

; установить наш обработчик
   mov   ax,251Ch   ; AH = 25h, AL = номер прерывания
   mov   dx,offset int1Ch_handler ; DS:DX - адрес обработчика
   int   21h      ; установить обработчик прерывания 1Ch

; здесь размещается собственно программа, например вызов command.com
   mov   ah,1
   int   21h      ; ожидание нажатия на любую клавишу
; конец программы

; восстановить предыдущий обработчик прерывания 1Сh
   mov   ax,251Ch      ; AH = 25h, AL = номер прерывания
   mov   dx,word ptr old_int1Ch+2
   mov   ds,dx
   mov   dx,word ptr cs:old_int1Ch ; DS:DX - адрес обработчика
   int   21h

bailout:

   ret

old_int1Ch dd   ? ; здесь хранится адрес предыдущего обработчика
start_position   dw 0   ; позиция на экране, в которую выводится текущее
         ; время
start   endp

; обработчик для прерывания 1Ch
; выводит текущее время в позицию start_position на экране (только в текстовом
; режиме)

int1Ch_handler   proc   far
   pusha      ; обработчик аппаратного прерывания
   push   es   ; должен сохранять ВСЕ регистры
   push   ds

   push   cs   ; на входе в обработчик известно только значение
   pop   ds   ; регистра CS
   mov   ah,02h   ; Функция 02h прерывания 1Ah:
   int   1Ah      ; чтение времени из RTC
   jc   exit_handler ; если часы заняты - в другой раз

; AL = час в BCD-формате
   call   bcd2asc   ; преобразовать в ASCII
   mov   byte ptr output_line[2],ah ; поместить их в
   mov   byte ptr output_line[4],al ; строку output_line

   mov   al,cl      ; CL = минута в BCD-формате
   call   bcd2asc
   mov   byte ptr output_line[10],ah
   mov   byte ptr output_line[12],al

   mov   al,dh      ; DH = секунда в BCD-формате
   call   bcd2asc
   mov   byte ptr output_line[16],ah
   mov   byte ptr output_line[18],al

   mov   cx,output_line_l   ; число байтов в строке - в CX
   push   0B800h
   pop   es         ; адрес в видеопамяти
   mov   di,word ptr start_position ; в ES:DI
   mov   si,offset output_line ; адрес строки в DS:SI
   cld
   rep movsb         ; скопировать строку
exit_handler:
   pop   ds      ; восстановить все регистры
   pop   es
   popa
   jmp   cs:old_int1Ch ; передать управление предыдущему
            ; обработчику

; процедура bcd2asc
; преобразует старшую цифру упакованного BCD-числа в AL в ASCII-символ в AH,
; а младшую цифру - в ASCII-символ в AL
bcd2asc      proc   near
   mov   ah,al
   and   al,0Fh   ; оставить младшие 4 бита в AL
   shr   ah,4      ; сдвинуть старшие 4 бита в AH
   or   ax,3030h   ; преобразовать в ASCII-символы
   ret
bcd2asc      endp

; строка " 00h 00:00" с атрибутом 1Fh (белый на синем) после каждого символа
output_line   db   ' ',f7h,'0',f7h,'0',f7h,':',f7h
      db   ' ',f7h,'0',f7h,'0',f7h,':',f7h
      db   '0',f7h,'0',f7h,' ',f7h
output_line_l   equ $-output_line

int1Ch_handler   endp

end start


Расчет значения для позиции на экране:
каждая буква - 2 байта (буква и цвет, каждый по байту)
80 столбцов, 24 строки... Т.е. размер экрана в байтах (для CGA, текстовый режим) 80 * 24 * 2 байтов.
Пример: Значение для начала второй строки - 160, третьей - 320, четвертой - 480...

Но теперь тему перенесут во флейм...

_________________
Более мощный компьютер глючит быстрее и точнее.


 

Member
Статус: Не в сети
Регистрация: 04.02.2003
Откуда: Москва
WhPh, спасибо тебе огромное!!! :beer:

Добавлено спустя 3 минуты, 42 секунды:
Ой, совсем забыл! Выход из проги осуществляется нажатием таинственной клавиши anykey :) Надо поменять её на backspace или x.
Теперь точно всё.

_________________
Каждый человек по-своему прав. А по-моему, нет.


 

Member
Статус: Не в сети
Регистрация: 12.03.2003
Откуда: Израиль
Вот переделанный кусок, по комментарию догадаешься куда его вставлять:
Код:
; здесь размещается собственно программа, например вызов command.com
waitloop:
   mov   ah,7
   int   21h      ; ожидание нажатия на любую клавишу
   cmp al, 'x'
   jnz waitloop
; конец программы

'x' можно менять на любой символ (в одинарных кавычках)
а также на любой ASCII-код (без кавычек)

А вообще такую тему надо было во флейм...

_________________
Более мощный компьютер глючит быстрее и точнее.


 

Member
Статус: Не в сети
Регистрация: 04.02.2003
Откуда: Москва
Цитата:
догадаешься куда его вставлять
После строки
Код:
end  start
? Или сразу перед ней? :)

Добавлено спустя 8 часов, 31 минуту, 43 секунды:
WhPh, ой, чё-то я ступил... =))
Спасибо тебе большое ещё раз!!!

_________________
Каждый человек по-своему прав. А по-моему, нет.


Показать сообщения за:  Поле сортировки  
Начать новую тему Новая тема / Ответить на тему Ответить  Сообщений: 7 
-

Часовой пояс: UTC + 3 часа


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 2


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Перейти:  
Создано на основе phpBB® Forum Software © phpBB Group
Русская поддержка phpBB | Kolobok smiles © Aiwan