текст программы (1071547)
Текст из файла
Московский Государственный Университет имени Н.Э. Баумана.
УТВЕРЖДАЮ
"___"__________1999 г.
_____________________
(Большаков С.А.)
Программа "Резидентные часы"
Текст программы
(тип документа)
Бумага формата А4
(вид носителя)
11
(количество листов)
ИСПОЛНИТЕЛЬ
" " 1999 г.
_____________________
(Бидяк И.Н.)
Москва – 1999
1 ;Курсовая работа по Системному программированию
2 ;"Резидентные часы" в текстовом режиме
3
4 ;директивы компиляции
5 0000 MODEL TINY ; модель памяти для .COM программы ( один сегмент для
6 ; кода+данные )
7 LOCALS ; разрешение использовать локальные метки ( @@Label )
8 P286 ; компилировать с использованием инструкций процессора 80286+
9 IDEAL ; специальный режим компиляции для уменьшения количества
10 ; возможных ошибок ( не совместим с MASM )
11 JUMPS ; автоматически преобразовывать
12 ; вот это в вот это
13 ;
14 ; cmp al, 3h cmp al, 3h
15 ; je CoolGirl ;(где CoolGirl-$ >127) jne Next_1
16 ; nop jmp CoolGirl
17 ; Next_1:
18 ; nop
19
20 ;включаем файл с наиболее часто используемыми константами
21 INCLUDE "const.asm"
1 22 ;номера прерываний
1 23 = 10h VIDEO_INT EQU 10h
1 24 = 16h KEYBOARD_INT EQU 16h
1 25 = 1Ah TIME_INT EQU 1Ah
1 26 = 1Ch USER_TIMER_INT EQU 1Ch
1 27 = 21h DOS_INT EQU 21h
1 28 = 2Fh MUX_INT EQU 2Fh
1 29 ;номера служб прерывания 10h
1 30 = 0000h SET_VIDEO_MODE EQU 0000h
1 31 = 0200h GOTO_X_Y EQU 0200h
1 32 = 0300h GET_CURSOR_DATA EQU 0300h
1 33 = 0600h SCROLL_WINDOW_UP EQU 0600h
1 34 = 0700h SCROLL_WINDOW_DOWN EQU 0700h
1 35 = 0F00h GET_VIDEO_MODE EQU 0F00h
1 36 ;номера служб прерывания 16h
1 37 = 0200h GET_SHIFT_FLAGS EQU 0200h
1 38 ;номера служб прерывания 1Ah
1 39 = 0200h READ_RTC_TIME EQU 0200h ; read_Real Time Clock_time
1 40 ;номера служб прерывания 21h
1 41 = 0100h GET_CHAR_WITH_ECHO EQU 0100h
1 42 = 0200h DISPLAY_CHAR EQU 0200h
1 43 = 0700h GET_CHAR_WITHOUT_ECHO EQU 0700h
1 44 = 0900h PRINT_STRING EQU 0900h
1 45 = 0A00h BUFFERED_STRING_INPUT EQU 0A00h
1 46 = 2500h SET_INT_VECTOR EQU 2500h
1 47 = 2A00h GET_DATE EQU 2A00h
1 48 = 2B00h SET_DATE EQU 2B00h
1 49 = 2C00h GET_TIME EQU 2C00h
1 50 = 2D00h SET_TIME EQU 2D00h
1 51 = 3100h TSR EQU 3100h
1 52 = 3400h GET_INDOS_FLAG_ADDRESS EQU 3400h
1 53 = 3500h GET_INT_VECTOR EQU 3500h
1 54 = 3C00h CREAT_FILE_V_HANDLE EQU 3C00h
1 55 = 3D00h OPEN_FILE_V_HANDLE EQU 3D00h
1 56 = 3E00h CLOSE_FILE_V_HANDLE EQU 3E00h
1 57 = 3F00h READ_FROM_FILE_V_HANDLE EQU 3F00h
1 58 = 4000h WRITE_TO_FILE_V_HANDLE EQU 4000h
1 59 = 4200h MOVE_FILE_POINTER EQU 4200h
1 60 = 4800h ALLOCATE_MEMORY EQU 4800h
1 61 = 4900h FREE_MEMORY EQU 4900h
1 62 = 4A00h RESIZE_MEMORY EQU 4A00h
1 63 = 4C00h FINISH_PROGRAM EQU 4C00h
1 64 = 6520h UPSHIFT_CHAR EQU 6520h
1 65 = 6521h UPSHIFT_STRING EQU 6521h
1 66 = 6522h UPSHIFT_ASCIIZ_STRING EQU 6522h
1 67 ;маски для флага состояния нажатия управляющих клавиш
1 68 = 00000001B RSHIFT EQU 00000001B
1 69 = 00000010B LSHIFT EQU 00000010B
1 70 = 00000100B CTRL EQU 00000100B
1 71 = 00001000B ALT EQU 00001000B
1 72 = 00010000B SCROLL EQU 00010000B
1 73 = 00100000B NUM EQU 00100000B
1 74 = 01000000B CAPS EQU 01000000B
1 75 = 10000000B INSERT EQU 10000000B
1 76 ;разное
1 77 = 0000h STDIN EQU 0000h
1 78 = 0001h STDOUT EQU 0001h
1 79 = 0002h STDERR EQU 0002h
1 80 = 002Ch ENV_SEG_START EQU 002Ch
1 81 = 0080h NUMBER_OF_COMMAND_LINE_PARAMETERS EQU 0080h
1 82 = 0081h COMMAND_LINE_START EQU 0081h
1 83 = 0100h PSP_SIZE EQU 0100h
1 84 ;коды для функции MOVE_FILE_POINTER
1 85 = 00000000b FROM_START EQU 00000000b
1 86 = 00000001b FROM_CURRENT_POSITION EQU 00000001b
1 87 = 00000010b FROM_END EQU 00000010b
1 88 ;коды доступа к открываемому файлу
1 89 = 00000000b READ_ONLY EQU 00000000b
1 90 = 00000001b WRITE_ONLY EQU 00000001b
1 91 = 00000010b READ_WRITE EQU 00000010b
1 92 ;аттрибуты файлов
1 93 = 00000000b NORMAL_FILE EQU 00000000b
1 94 = 00000001b READ_ONLY_FILE EQU 00000001b
1 95 = 00000010b HIDDEN_FILE EQU 00000010b
1 96 = 00000100b SYSTEM_FILE EQU 00000100b
1 97 = 00010000b ARCHIVE_FILE EQU 00010000b
1 98 ;управляющие символы из таблицы ASCII
1 99 = 10d LINE_FEED EQU 10d
1 100 = 13d CARRIAGE_RETURN EQU 13d
1 101
102
103 ;директивы управления сегментами ( в нашем случае он только один )
104 0000 SEGMENT Code PARA PUBLIC 'CODE'
105 ASSUME CS:Code, DS:NOTHING, ES:NOTHING
106 ;указатель на начало резидентной части
107 0000 LABEL First_Byte_Of_TSR_Part BYTE
108 ;это для того, чтобы знать адрес сегмента окружения ( Enviroment Segment )
109 ORG ENV_SEG_START
110 002C LABEL Env_Seg WORD
111 ;это для того, чтобы знать адрес количества параметров в командной строке
112 ORG NUMBER_OF_COMMAND_LINE_PARAMETERS
113 0080 LABEL Number_Of_Parameters BYTE
114 ;нормальный ORG для все .COM программ
115 ORG PSP_SIZE
116
117 ;начало программы
118 0100 Program_Start:
119 0100 E9 0135 jmp Initialize ;пропускаем данные и резидентную часть
120
121 ;типы
122
123 ;данные, используемые в резидентной части программы
124 ;адрес начала видеопамяти( только для CGA, EGA, VGA карт )
125 0103 0000 Video_Memory_Start DW 0000h ; смещение
126 0105 B800 DW 0B800h ; сегмент
127 ;строка, в которой формируется время, и которая выводится потом на экран
128 0107 48 48 3A 4D 4D 3A 53+ Time_String DB 'HH:MM:SS$'
129 53 24
130 ;строка, в которой будет хранится та часть экрана, которую мы перезаписываем
131 0110 5F 5F 5F 5F 5F 5F 5F+ Temp_String DB '________________',0
132 5F 5F 5F 5F 5F 5F 5F+
133 5F 5F 00
134 ;адрес старого обработчика прерывания 09h ( ввод/вывод клавиатуры )
135 0121 00000000 Old_09_Vector DD 0
136 ;адрес старого обработчика прерывания 1Ch ( пользовательский таймер )
137 0125 00000000 Old_1C_Vector DD 0
138 ;адрес старого обработчика прерывания 2Fh ( мультиплексор )
139 0129 00000000 Old_2F_Vector DD 0
140 ;код, который будет возвращать программа при завершении
141 012D 00 Exit_Code DB 0
142 ;состояние часов ( если = 0 => часы скрыты, если = 1 => часы видны )
143 012E 00 Clock_Status DB 0 ; сначала скрыты
144 ;скан-код клавиши, которой мы переключаем видимость часов
145 012F 2E Switch_Key DB 2Eh ; 58h, 88d = F12
146 ; 2Eh, 46d = 'C'
147 ;флаги горячей клавиши ( той, которой мы переключаем видимость часов )
148 = 00001100B KeyFlagByte EQU 00001100B
149 ;маска для маскировки бит клавиш Scroll, Caps, Numlock в KeyFlagByte
150 = 00001111B LockKeyMask EQU 00001111B
151
152 ;включаем процедуры обработки прерываний 16h, 1Ch, 09h
153
154 INCLUDE "tsrprocs.asm"
1 155
1 156 ;------------------------------------------------------------------------------
1 157
1 158 ;процедура обработки прерывания 09h
1 159 0130 PROC New_09_Vector FAR
1 160 ;запоминаем используемые регистры
1 161 0130 60 pusha
1 162 0131 1E push ds
1 163 0132 06 push es
1 164 ;получаем скан-код нажатой клавиши
1 165 0133 E4 60 in al, 60h
1 166 0135 2E: 3A 06 012Fr cmp al, [ BYTE PTR cs:Switch_Key ]
1 167 013A 75 37 jne @@Exit_Procedure ; если не совпало => сразу вызываем старый
1 168 ; обработчик прерывания
1 169 ;совпало => проверяем флаги горячей клавиши
1 170 013C B8 0200 mov ax, GET_SHIFT_FLAGS
1 171 013F CD 16 int KEYBOARD_INT ; получаем флаги клавиатуры
1 172 0141 24 0F and al, LockKeyMask ; маскируем ненужные биты
1 173 0143 3C 0C cmp al, KeyFlagByte ; сравниваем с теми, которые нужны
1 174 0145 75 2C jne @@Exit_Procedure ; несовпало => вызываем старый обработчик
1 175 ;совпало => проверяем, что мы должны сделать ( скрыть или показать часы )
1 176 0147 2E: 80 3E 012Er 00 cmp [ BYTE PTR cs:Clock_Status ], 00h ; часы видны ? ( если 0 - то нет )
1 177 014D 75 0F jne @@Restore_Screen; да видны
1 178 ;нет часы не видны => запоминаем часть экрана, которая будет занята часами
1 179 ;часы всегда будут располагаться в левом верхнем углу экрана
1 180 014F 2E: C5 36 0103r lds si, [ DWORD PTR cs:Video_Memory_Start ] ; адрес начала запоминаемой области
1 181 0154 0E push cs ; указываем адрес строки, где будет хранится
1 182 0155 07 pop es ; запоминаемая часть экрана
1 183 0156 BF 0110r mov di, OFFSET Temp_String
1 184 0159 B9 0008 mov cx, 08h ;копироваться будет восемь слов ( символ + его аттрибут )
1 185 015C F3> A5 rep movsw ;собственно копируем
1 186 015E @@Restore_Screen:
1 187 ;восстанавливаем экран, который был под часами
1 188 015E 2E: C4 3E 0103r les di, [ DWORD PTR cs:Video_Memory_Start ] ; адрес начала восстанавливаемой области
1 189 0163 0E push cs ; указываем адрес строки, откуда будет браться
1 190 0164 1F pop ds ; запомненная часть экрана
1 191 0165 BE 0110r mov si, OFFSET Temp_String
1 192 0168 B9 0008 mov cx, 08h ;копироваться будет восемь слов ( символ + его аттрибут )
1 193 016B F3> A5 rep movsw ;собственно копируем
1 194 ;меняем Clock_Status на противоположный
1 195 016D 2E: 80 36 012Er 01 xor [ BYTE PTR cs:Clock_Status ], 01h ;совершенно отбалдешное число
1 196 0173 @@Exit_Procedure:
1 197 ;восстанавливаем использовавшиеся регистры
1 198 0173 07 pop es
1 199 0174 1F pop ds
1 200 0175 61 popa
1 201 ;вызываем старый обработчик прерывания
1 202 0176 9C pushf
1 203 0177 FA cli
1 204 0178 2E: FF 1E 0121r call [ DWORD PTR cs:Old_09_Vector ]
1 205 017D FB sti
1 206 ;возвращаемся из процедуры обработки прерывания
1 207 017E CF iret
1 208 017F ENDP New_09_Vector
1 209
1 210 ;------------------------------------------------------------------------------
1 211
1 212 ;процедура обработки прерывания 1Ch
1 213 017F PROC New_1C_Vector FAR
1 214 ;вызываем старый (оригинальный) обработчик прерывания
1 215 017F 9C pushf
1 216 0180 2E: FF 1E 0125r call [ DWORD PTR cs:Old_1C_Vector ]
1 217 ;проверяем: а надо ли нам вообще показывать часы ?
1 218 0185 2E: 80 3E 012Er 00 cmp [ BYTE PTR cs:Clock_Status ], 00h
1 219 018B 75 01 jne @@Proceed
1 220 ;возвращаемся из процедуры
1 221 018D CF iret
1 222 018E @@Proceed:
1 223 ;сохраняем используемые регистры
1 224 018E 60 pusha
1 225 018F 1E push ds
1 226 0190 06 push es
1 227 ;запрещаем аппаратные прерывания
1 228 0191 FA cli
1 229 ;узнаем время BIOS
1 230 0192 @@Get_Time:
1 231 0192 B8 0200 mov ax, READ_RTC_TIME
1 232 0195 CD 1A int TIME_INT
1 233 0197 72 F9 jc @@Get_Time ; повторяем пока не получим таки время ( т.к. BIOS может и
1 234 ; не возвратить нам его с первого раза )
1 235 ;Формируем строку со временем, которую будем выводить на экран
1 236 ;устанавливаем CS:DI на начало нашей строки
1 237 0199 BF 0107r mov di, OFFSET Time_String
1 238 ;преобразовываем часы в ASCII формат
1 239 019C 8A E5 mov ah, ch
1 240 019E C0 E8 04 shr al, 4
1 241 01A1 C0 E0 04 shl al, 4
1 242 01A4 2A E0 sub ah, al
1 243 01A6 C0 E8 04 shr al, 4
1 244 01A9 05 3030 add ax, 3030h
1 245 ;преобразовываем минуты в ASCII формат
1 246 01AC 8A F9 mov bh, cl
1 247 01AE 8A D9 mov bl, cl
1 248 01B0 C0 EB 04 shr bl, 4
1 249 01B3 C0 E3 04 shl bl, 4
1 250 01B6 2A FB sub bh, bl
1 251 01B8 C0 EB 04 shr bl, 4
1 252 01BB 81 C3 3030 add bx, 3030h
1 253 ;преобразовываем секунды в ASCII формат
1 254 01BF 8A EE mov ch, dh
1 255 01C1 8A CE mov cl, dh
1 256 01C3 C0 E9 04 shr cl, 4
1 257 01C6 C0 E1 04 shl cl, 4
1 258 01C9 2A E9 sub ch, cl
1 259 01CB C0 E9 04 shr cl, 4
1 260 01CE 81 C1 3030 add cx, 3030h
1 261 ;записываем в строку часы
1 262 01D2 2E: A3 0107r mov [ WORD PTR cs:Time_String ], ax
Характеристики
Тип файла документ
Документы такого типа открываются такими программами, как Microsoft Office Word на компьютерах Windows, Apple Pages на компьютерах Mac, Open Office - бесплатная альтернатива на различных платформах, в том числе Linux. Наиболее простым и современным решением будут Google документы, так как открываются онлайн без скачивания прямо в браузере на любой платформе. Существуют российские качественные аналоги, например от Яндекса.
Будьте внимательны на мобильных устройствах, так как там используются упрощённый функционал даже в официальном приложении от Microsoft, поэтому для просмотра скачивайте PDF-версию. А если нужно редактировать файл, то используйте оригинальный файл.
Файлы такого типа обычно разбиты на страницы, а текст может быть форматированным (жирный, курсив, выбор шрифта, таблицы и т.п.), а также в него можно добавлять изображения. Формат идеально подходит для рефератов, докладов и РПЗ курсовых проектов, которые необходимо распечатать. Кстати перед печатью также сохраняйте файл в PDF, так как принтер может начудить со шрифтами.