; Procedury pobierania oraz ustawiania daty i czasu ; ; Autor: Bogdan 'bogdro' Drozdowski ; Data/Wersja: 18.03.2006 ; minimalny i maksymalny dopuszczany rok do ustawienia prawidlowej daty %define ROK_MIN 1980 %define ROK_MAX ROK_MIN+99 section .text global _gettime global _settime global _getdate global _setdate ; =================================================================== ; void gettime ( int *godzina, int *minuta, int *sekunda ); _gettime: push ebp mov ebp, esp ; [ebp] = stary EBP ; [ebp+4] = adres powrotny ; [ebp+8] = arg1 ; [ebp+12] = arg2 ; [ebp+16] = arg3 %define p_godzina ebp+8 %define p_minuta ebp+12 %define p_sekunda ebp+16 pushfd push eax push edx push esi xor eax, eax xor edx, edx mov dl, 0edh ; port opozniajacy mov al, 4 ; godziny (spakowany BCD) out 70h, al out dx, al ; opoznienie in al, 71h ; AL = numer godziny w BCD mov ah, al shr ah, 4 and al, 0fh aad ; AL = numer godziny binarnie mov esi, [p_godzina] mov [esi], eax mov al, 2 ; minuty (s. BCD) out 70h, al out dx, al in al, 71h ; AL = numer minuty w BCD mov ah, al shr ah, 4 and al, 0fh aad ; AL = numer minuty binarnie mov esi, [p_minuta] mov [esi], eax xor al, al ; sekundy (s. BCD) out 70h, al out dx, al in al, 71h ; AL = numer sekundy w BCD mov ah, al shr ah, 4 and al, 0fh aad ; AL = numer sekundy binarnie mov esi, [p_sekunda] mov [esi], eax pop esi pop edx pop eax popfd leave ret ; =================================================================== ; int settime ( int godzina, int minuta, int sekunda ); _settime: push ebp mov ebp, esp %define godzina ebp+8 %define minuta ebp+12 %define sekunda ebp+16 pushfd push ebx push edx ; sprawdzenie danych: cmp dword [godzina], 23 ja .blad cmp dword [minuta], 59 ja .blad cmp dword [sekunda], 59 ja .blad ; ladowanie danych do CMOS: mov dx, 0edh ; port opozniajacy mov bl, 10 ; dzielnik do operacji bin->BCD div bl ; AL = (sekunda / 10); AH = ( sekunda mod 10 ) shl al, 4 or ah, al ; AH = sekundy w BCD xor al, al ; AL = 0 = pole sekund out 70h, al mov al, ah out dx, al out 71h, al ; zapisalo sekundy mov eax, [minuta] div bl ; AL = (minuta / 10); AH = ( minuta mod 10 ) shl al, 4 or ah, al ; AH = minuty w BCD mov al, 2 ; AL = 2 = pole minut out 70h, al mov al, ah out dx, al out 71h, al ; zapisalo minuty mov eax, [godzina] div bl ; AL = (godzina / 10); AH = ( godzina mod 10 ) shl al, 4 or ah, al ; AH = godzina w BCD mov al, 4 ; AL = 4 = pole godzin out 70h, al mov al, ah out dx, al out 71h, al ; zapisalo godzine xor eax, eax ; zwracamy 0 (brak bledu) jmp .koniec .blad: or eax, -1 .koniec: pop edx pop ebx popfd leave ret ; =================================================================== ; void getdate ( int *rok, int *miesiac, int *dzien ); _getdate: push ebp mov ebp, esp %define p_rok ebp+8 %define p_miesiac ebp+12 %define p_dzien ebp+16 pushfd push eax push ebx push edx push esi xor eax, eax mov bl, 100 ; mnoznik, bo caly rok = stulecie * 100 + rok mov dx, 0edh ; port opozniajacy mov al, 50 ; stulecie (spakowany BCD) out 70h, al out dx, al ; opoznienie in al, 71h ; AL = numer stulecia w BCD mov ah, al shr ah, 4 and al, 0fh aad ; AL = numer stulecia binarnie mul bl ; AX = AL*BL = stulecie * 100 mov ebx, eax ; EBX = 100 * stulecie mov al, 9 ; ostatnie 2 cyfry roku (spakowany BCD) out 70h, al out dx, al ; opoznienie in al, 71h ; AL = numer roku w BCD mov ah, al shr ah, 4 and al, 0fh aad ; AL = numer roku binarnie add ebx, eax ; EBX = caly rok mov esi, [p_rok] mov [esi], ebx mov al, 8 ; miesiac (s. BCD) out 70h, al out dx, al in al, 71h ; AL = numer miesiaca w BCD mov ah, al shr ah, 4 and al, 0fh aad ; AL = numer miesiaca binarnie mov esi, [p_miesiac] mov [esi], eax mov al, 7 ; dzien (s. BCD) out 70h, al out dx, al in al, 71h ; AL = numer dnia w BCD mov ah, al shr ah, 4 and al, 0fh aad ; AL = numer dnia binarnie mov esi, [p_dzien] mov [esi], eax pop esi pop edx pop ebx pop eax popfd leave ret ; =================================================================== ; int setdate ( int rok, int miesiac, int dzien ); _setdate: push ebp mov ebp, esp %define rok ebp+8 %define miesiac ebp+12 %define dzien ebp+16 pushfd push ebx push edx ; sprawdzenie danych: mov eax, [miesiac] cmp eax, 12 ja .blad test eax, eax ; spr, czy miesiac != 0 jz .blad mov eax, [ __dni + eax*4 - 4 ] ; EAX = liczba dni w danym miesiacu mov edx, [dzien] cmp edx, eax ja .blad test edx, edx ; spr, czy dzien != 0 jz .blad mov eax, [rok] cmp eax, ROK_MIN jl .blad cmp eax, ROK_MAX jg .blad cmp dword [miesiac], 2 jne .laduj ; dalej sprawdzamy feralny luty w latach przestepnych cmp dword [dzien], 28 jbe .laduj ; sprawdzamy tylko jest ktos chce ustawic 29.II ; sprawdzenie lat przestepnych: ; jesli ( rok % 4 == 0 ) && !( rok % 100 == 0 ) || ( rok % 400 == 0 ) , to rok jest przestepny mov ebx, 400 xor edx, edx div ebx ; EDX = rok % 400 test edx, edx ; EDX = 0 <==> rok % 400 == 0, wiec jest przestepny. jz .laduj mov eax, [rok] mov ebx, 100 xor edx, edx div ebx ; EDX = rok % 100 test edx, edx ; EDX = 0 <==> rok % 100 == 0, czyli nie jest przestepny jz .blad mov eax, [rok] and eax, 3 ; EAX = rok % 4. Jesli EAX != 0, to nie jest przestepny jnz .blad .laduj: ; ladowanie danych do CMOS: mov dx, 0edh ; port opozniajacy mov bl, 10 ; dzielnik do operacji bin->BCD mov eax, [dzien] div bl ; AL = (dzien / 10); AH = ( dzien mod 10 ) shl al, 4 or ah, al ; AH = dzien w BCD mov al, 7 ; AL = 7 = pole dnia out 70h, al mov al, ah out dx, al out 71h, al ; zapisalo dzien mov eax, [miesiac] div bl ; AL = (miesiac / 10); AH = ( miesiac mod 10 ) shl al, 4 or ah, al ; AH = miesiac w BCD mov al, 8 ; AL = 8 = pole miesiaca out 70h, al mov al, ah out dx, al out 71h, al ; zapisalo miesiac mov eax, [rok] mov bl, 100 div bl ; AL = (rok / 100); AH = ( rok mod 100 ) mov bl, 10 shr ax, 8 ; AX = AH = rok mod 100 = 2 ostatnie cyfry div bl shl al, 4 or ah, al ; AH = rok w BCD mov al, 9 ; AL = 9 = pole ostatnich dwoch cyfr roku out 70h, al mov al, ah out dx, al out 71h, al ; zapisalo rok mov eax, [rok] mov bl, 100 div bl ; AL = (rok / 100); AH = ( rok mod 100 ) mov bl, 10 xor ah, ah ; AX = AL = rok / 100 = stulecie div bl shl al, 4 or ah, al ; AH = stulecie w BCD mov al, 50 ; AL = 50 = pole stulecia out 70h, al mov al, ah out dx, al out 71h, al ; zapisalo stulecie xor eax, eax ; zwracamy 0 (brak bledu) jmp .koniec .blad: or eax, -1 .koniec: pop edx pop ebx popfd leave ret section .data ; liczby dni w kazdym miesiacu __dni: dd 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31