Бывалый
Профиль
Группа: Участник
Сообщений: 219
Регистрация: 20.12.2007
Репутация: нет Всего: 1
|
Оставлю ту всю программу Код | org 07C00h
USE16 main: cli
lgdt [cs:GDTR] ; Загрузка адреса глобальной таблицы дескрипторов
mov eax, cr0 ; Переключение в защищенный режим or al,1 mov cr0,eax jmp CODE_SELECTOR:pm_start
NULL_SELECTOR = 0 ; Нулевой селектор CODE_SELECTOR = 1 shl 3 ; Селектор кода DATA_SELECTOR = 2 shl 3 ; Селектор данных VIDEO_SELECTOR = 3 shl 3 ; Селектор буфера видеопамяти
GDTR: ; Global Descriptors Table Register dw 4*8-1 ; Размер GDT dq GDT ; Смещение GDT GDT: ; нулевой дескриптор (обязательно должен присутствовать в GDT!) NULL_descr db 8 dup (0) ; дескриптор 32-разрядного сегмента кода: база = 00000000h, размер = FFFFFFFFh CODE_descr db 0FFh, 0FFh, 00h, 00h, 00h, 10011010b, 11001111b , 00h ; дескриптор 32-разрядного сегмента данных: база = 00000000h, размер = FFFFFFFFh DATA_descr db 0FFh, 0FFh, 00h, 00h, 00h, 10010010b, 11001111b , 00h ; дескриптор сегмента видеопамяти: база = 000B8000h, размер = 0000FFFFh VIDEO_descr db 0FFh, 0FFh, 00h, 80h, 0Bh, 10010010b, 01000000b , 00h
;Этот код исполняется в защищенном режиме ;=======================================================; USE32
pm_start:
mov AX, VIDEO_SELECTOR ; селектор на третий дескриптор (VIDEO_descr) mov ES, AX ; а этого в ES mov AX, DATA_SELECTOR mov DS, AX
;Счетчик символов для вывода на экран mov di, 0
call print_date call read_and_set_date call print_date
exit_: ; завешиваем компьютер hlt
;Печать значения минуты и секунды print_date: ; "minute:" mov bx, str_min call print_string
; Значение минут mov al, 02H out 70H, al ;выбрать адрес CMOS 02H jmp $+2 ;требуется небольшая задержка in al, 71H ;теперь в AL искомое значение call bcd_to_hex mov cl, al call print_6bit_in_oct
; Новая строка call print_new_line
; "second:" mov bx, str_sec call print_string
; Значение секунд mov al, 00H out 70H, al ;выбрать адрес CMOS 00H jmp $+2 ;требуется небольшая задержка in al, 71H ;теперь в AL искомое значение call bcd_to_hex mov cl, al mov ah, 0Eh call print_6bit_in_oct
; Новая строка call print_new_line
ret;
;Преобразование BCD-кода в HEX bcd_to_hex: ;перенос старшей цифры в ah mov ah, al shr ah, 4 and al, 0Fh ;команда принимает в ah старшую цифру, в al - младшую aad ret
;Преобразование HEX в BCD-код hex_to_bcd: mov ah, 0 ;команда помещает старшую цифру в ah aam ;объединение ah и al shl ah, 4 or al, ah ret
;процедура вывода 6 младших бит в восьмиричной системе счисления на экран ;байт передается в cl print_6bit_in_oct: ;старшая цифра mov al, cl shr al, 3 and al, 07h add al, '0' call print_char ;младшая цифра mov al, cl and al, 07h add al, '0' call print_char
ret
;вывод на экран строки, оканчивающейся нулем ;адрес сроки передается в ds:bx ;адрес видеопамяти передается в es:di print_string:
mov ah, 0 ; вывод текущего знака .char: mov al,[bx] inc bx
;окончание строки на нулевом символе test al,al jz .ret
;Вывод символа call print_char
jmp .char .ret: ret
; Перевод строки ; Для этого указатель di устанавливается на следующее занчение, кратное 160 ; размер экрана 80х25, по 2 байта на символ ;новое значение высчитыватся по формуле: di = 160 * ( ( di / 160 ) + 1 ) print_new_line: ; di / 160 mov ax, di mov bl, 160 div bl ; ( di / 160 ) + 1 inc al ; 160 * ( ( di / 160 ) + 1 ) mul bl mov di, ax ret;
; Вывод одного символа на экран print_char: ;цвет - белый по черному mov ah, 0Fh ;вывод mov [es:di], ax ;смещение в следующую позицию add di, 2 ret
; Чтение из консоли даты и установка в CMOS read_and_set_date:
; "minute:" mov bx, str_min call print_string
; Значение минут call read_two_oct_digits_to_byte mov al, 02H out 70H, al ;выбрать адрес CMOS 02H mov al, bl call hex_to_bcd out 71H, al ;отправка нового значения в порт
; Перенос строки call print_new_line
; "second:" mov bx, str_sec call print_string
; Значение секунд call read_two_oct_digits_to_byte mov al, 00H out 70H, al ;выбрать адрес CMOS 00H mov al, bl call hex_to_bcd out 71H, al ;отправка нового значения в порт
; Перенос строки call print_new_line
ret
;считывание 4х восьмиричных цифр ;результат в bl read_two_oct_digits_to_byte: ;результат mov bl, 0 ;счетчик цифр mov cx, 2 .digit:
;операция считывания ;считываем из порта 64 состояние ;при установке младшего бита в 1 произошло нажатиие .wait: in al, 64h test al, 1h jz .wait
;scan-код нажатия получаем из порта 60 in al, 60h
;преобразуем scan-код 0 (0Bh) в скан-код 01h cmp al, 0bh jne .decode mov al, 01h .decode:
;проверка на правильную восьмеричную цифру cmp al, 1 jl .digit cmp al, 08h jg .digit
;преобразование из скан-кода в цифру sub al, 01h
;учитываем считанное значение в результат shl bl, 3 or bl, al
; код функции вывода на экран add al, '0' call print_char
;переходим к следующей цифре dec cx jnz .digit
ret
; СТРОКИ str_min db 'minute:',0 str_sec db 'second:',0
; эта директива заставляет компилятор заполнить оставшееся (до 512-и байт) место нулями times 510-($-main) db 0 ; а эти два байта нужны чтобы биос определил что это действительно ; бут сектор dw 0xAA55
|
Да, забыл, пишу на FASM Это сообщение отредактировал(а) BIV - 25.5.2013, 13:03
|