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 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 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, спасибо тебе огромное!!!
Добавлено спустя 3 минуты, 42 секунды: Ой, совсем забыл! Выход из проги осуществляется нажатием таинственной клавиши anykey Надо поменять её на backspace или x.
Теперь точно всё.
_________________ Каждый человек по-своему прав. А по-моему, нет.
Member
Статус: Не в сети Регистрация: 12.03.2003 Откуда: Израиль
Вот переделанный кусок, по комментарию догадаешься куда его вставлять:
Код:
; здесь размещается собственно программа, например вызов command.com waitloop: mov ah,7 int 21h ; ожидание нажатия на любую клавишу cmp al, 'x' jnz waitloop ; конец программы
'x' можно менять на любой символ (в одинарных кавычках)
а также на любой ASCII-код (без кавычек)
А вообще такую тему надо было во флейм...
_________________ Более мощный компьютер глючит быстрее и точнее.
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 2
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения