Добавил 2-ю лабу по осям за 4 сем
parent
cdb9116713
commit
15671d75a8
|
@ -0,0 +1,159 @@
|
||||||
|
.intel_syntax noprefix
|
||||||
|
|
||||||
|
.code16
|
||||||
|
.global _start
|
||||||
|
_start:
|
||||||
|
xor ax, ax # Clear AX
|
||||||
|
mov ds, ax # Set DS to 0
|
||||||
|
mov es, ax # Set ES to 0
|
||||||
|
mov ss, ax # Set SS to 0
|
||||||
|
mov sp, 0x7C00 # Set stack pointer
|
||||||
|
|
||||||
|
mov ax, 0x1000 # Load the address where the disk is located
|
||||||
|
mov es, ax # Set ES to point to this location
|
||||||
|
mov bx, 0 # BX = 0
|
||||||
|
mov ah, 2 # Read sectors function
|
||||||
|
mov dl, 1 # Drive number (1 = first floppy)
|
||||||
|
mov dh, 0 # Head number
|
||||||
|
mov cl, 1 # Starting sector (1)
|
||||||
|
mov ch, 0 # Cylinder number
|
||||||
|
mov al, 88 # Number of sectors to read
|
||||||
|
int 0x13 # BIOS interrupt to read sectors
|
||||||
|
|
||||||
|
mov ax, 0x0003
|
||||||
|
int 0x10
|
||||||
|
|
||||||
|
LOAD:
|
||||||
|
xor cx, cx
|
||||||
|
xor dx, dx
|
||||||
|
mov eax, 0xe801
|
||||||
|
int 0x15
|
||||||
|
mov [0x3400], cx # Количество Кб до 16 Мб
|
||||||
|
mov [0x3420], dx # Количество страниц размером 64 Кб
|
||||||
|
|
||||||
|
LOADING_OS_PRINT:
|
||||||
|
mov ah, 0x0e
|
||||||
|
mov al, 'L'
|
||||||
|
int 0x10
|
||||||
|
mov al, 'o'
|
||||||
|
int 0x10
|
||||||
|
mov al, 'a'
|
||||||
|
int 0x10
|
||||||
|
mov al, 'd'
|
||||||
|
int 0x10
|
||||||
|
mov al, 'i'
|
||||||
|
int 0x10
|
||||||
|
mov al, 'n'
|
||||||
|
int 0x10
|
||||||
|
mov al, 'g'
|
||||||
|
int 0x10
|
||||||
|
mov al, ' '
|
||||||
|
int 0x10
|
||||||
|
mov al, 'O'
|
||||||
|
int 0x10
|
||||||
|
mov al, 'S'
|
||||||
|
int 0x10
|
||||||
|
mov al, '.'
|
||||||
|
int 0x10
|
||||||
|
mov al, '.'
|
||||||
|
int 0x10
|
||||||
|
mov al, '.'
|
||||||
|
int 0x10
|
||||||
|
mov al, ' '
|
||||||
|
int 0x10
|
||||||
|
mov al, 'P'
|
||||||
|
int 0x10
|
||||||
|
mov al, 'r'
|
||||||
|
int 0x10
|
||||||
|
mov al, 'e'
|
||||||
|
int 0x10
|
||||||
|
mov al, 's'
|
||||||
|
int 0x10
|
||||||
|
mov al, 's'
|
||||||
|
int 0x10
|
||||||
|
mov al, ' '
|
||||||
|
int 0x10
|
||||||
|
mov al, 's'
|
||||||
|
int 0x10
|
||||||
|
mov al, 'p'
|
||||||
|
int 0x10
|
||||||
|
mov al, 'a'
|
||||||
|
int 0x10
|
||||||
|
mov al, 'c'
|
||||||
|
int 0x10
|
||||||
|
mov al, 'e'
|
||||||
|
int 0x10
|
||||||
|
mov al, ' '
|
||||||
|
int 0x10
|
||||||
|
mov al, 't'
|
||||||
|
int 0x10
|
||||||
|
mov al, 'o'
|
||||||
|
int 0x10
|
||||||
|
mov al, ' '
|
||||||
|
int 0x10
|
||||||
|
mov al, 'c'
|
||||||
|
int 0x10
|
||||||
|
mov al, 'o'
|
||||||
|
int 0x10
|
||||||
|
mov al, 'n'
|
||||||
|
int 0x10
|
||||||
|
mov al, 't'
|
||||||
|
int 0x10
|
||||||
|
mov al, 'i'
|
||||||
|
int 0x10
|
||||||
|
mov al, 'n'
|
||||||
|
int 0x10
|
||||||
|
mov al, 'u'
|
||||||
|
int 0x10
|
||||||
|
mov al, 'e'
|
||||||
|
int 0x10
|
||||||
|
mov al, '!'
|
||||||
|
int 0x10
|
||||||
|
|
||||||
|
input:
|
||||||
|
mov ah, 0
|
||||||
|
int 0x16
|
||||||
|
cmp al, 0x20
|
||||||
|
jne input
|
||||||
|
mov ax, 0x03
|
||||||
|
int 0x10
|
||||||
|
|
||||||
|
COMPLETE:
|
||||||
|
mov ax, 0x3 # Read character from keyboard
|
||||||
|
int 0x10 # BIOS interrupt for video services
|
||||||
|
|
||||||
|
lgdt gdt_info # Load GDT
|
||||||
|
cli # Clear interrupts
|
||||||
|
in al, 0x70 # Read from port 0x70
|
||||||
|
or al, 0x80 # Set bit 7
|
||||||
|
out 0x70, al # Write back to port 0x70
|
||||||
|
|
||||||
|
mov eax, cr0 # Read control register 0
|
||||||
|
or al, 1 # Set PE bit to enter protected mode
|
||||||
|
mov cr0, eax # Write back to CR0
|
||||||
|
|
||||||
|
jmp 0x8:protected_mode # Jump to protected mode
|
||||||
|
|
||||||
|
.code32
|
||||||
|
protected_mode:
|
||||||
|
mov ax, 0x10 # Load data segment selector
|
||||||
|
mov es, ax # Set ES
|
||||||
|
mov ds, ax # Set DS
|
||||||
|
mov ss, ax # Set SS
|
||||||
|
|
||||||
|
call 0x10000 # Call code at new segment
|
||||||
|
|
||||||
|
inf_loop:
|
||||||
|
jmp inf_loop # Infinite loop
|
||||||
|
|
||||||
|
gdt:
|
||||||
|
.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||||
|
.byte 0xff, 0xff, 0x00, 0x00, 0x00, 0x9A, 0xCF, 0x00
|
||||||
|
.byte 0xff, 0xff, 0x00, 0x00, 0x00, 0x92, 0xCF, 0x00
|
||||||
|
gdt_info:
|
||||||
|
.word gdt_info - gdt
|
||||||
|
.word gdt, 0
|
||||||
|
|
||||||
|
# Reserve space to ensure we have a valid boot sector
|
||||||
|
.zero (512 - ($ - _start) - 2)
|
||||||
|
.byte 0x55, 0xAA
|
|
@ -0,0 +1,831 @@
|
||||||
|
/*
|
||||||
|
as --32 -o bootsect.o bootsect.asm
|
||||||
|
ld -Ttext 0x7c00 --oformat binary -m elf_i386 -o bootsect.bin bootsect.o
|
||||||
|
g++ -ffreestanding -m32 -o kernel.o -c kernel.cpp
|
||||||
|
ld --oformat binary -Ttext 0x10000 -o kernel.bin --entry=kmain -m elf_i386 kernel.o
|
||||||
|
qemu -fda bootsect.bin -fdb kernel.bin
|
||||||
|
*/
|
||||||
|
|
||||||
|
__asm("jmp kmain");
|
||||||
|
|
||||||
|
#define NWORD 456
|
||||||
|
#define CLR 0x02
|
||||||
|
#define VIDEO_BUF_PTR (0xb8000)
|
||||||
|
#define IDT_TYPE_INTR (0x0E)
|
||||||
|
#define IDT_TYPE_TRAP (0x0F)
|
||||||
|
#define PIC1_PORT (0x20)
|
||||||
|
#define CURSOR_PORT (0x3D4)
|
||||||
|
#define VIDEO_WIDTH (80)
|
||||||
|
#define GDT_CS (0x8)
|
||||||
|
|
||||||
|
char avb_letter[27] = { 0 };
|
||||||
|
int avb_letter_cnt[26] = { 0 };
|
||||||
|
int rand = 0x12000;
|
||||||
|
const char* empty_str = " ";
|
||||||
|
int str_num = 0;
|
||||||
|
int offset = 0;
|
||||||
|
unsigned int ticks = 0;
|
||||||
|
char time_os_loaded[15] = { 0 };
|
||||||
|
unsigned short mem_h = 0;
|
||||||
|
unsigned short mem_l = 0;
|
||||||
|
|
||||||
|
char strlen(const char *str)
|
||||||
|
{
|
||||||
|
const char *s;
|
||||||
|
|
||||||
|
for (s = str; *s; ++s)
|
||||||
|
;
|
||||||
|
return (s - str);
|
||||||
|
}
|
||||||
|
|
||||||
|
char strncmp(char *s1, char* s2, int len)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
while (*s1 && *s2 && i < len)
|
||||||
|
{
|
||||||
|
if (*s1 != *s2)
|
||||||
|
{
|
||||||
|
return (*s1 - *s2);
|
||||||
|
}
|
||||||
|
s1++;
|
||||||
|
s2++;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
if (i == len)
|
||||||
|
{
|
||||||
|
s1--;
|
||||||
|
s2--;
|
||||||
|
}
|
||||||
|
return (*s1 - *s2);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int kbd_scan[44] = {
|
||||||
|
0x1e, 0x30, 0x2e, 0x20, 0x12, 0x21, 0x22, 0x23, 0x17, 0x24, 0x25, 0x26, 0x32, 0x31, 0x18, 0x19, 0x10, 0x13, 0x1f, 0x14, 0x16, 0x2f, 0x11, 0x2d, 0x15, 0x2c, 0x39, 0x0d, 0x0c, 0x35, 0x1c, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0e, 0x2a, 0xAA };
|
||||||
|
char alphabet[32] = "abcdefghijklmnopqrstuvwxyz +-/*";
|
||||||
|
bool is_shift_pressed = false;
|
||||||
|
|
||||||
|
char command[41] = { 0 };
|
||||||
|
|
||||||
|
//OBRABOTKA PRERIVANIY KLAVIATURY
|
||||||
|
//////////////////////////////////////////////////////////////////
|
||||||
|
static inline unsigned char inb(unsigned short port)
|
||||||
|
{
|
||||||
|
unsigned char data;
|
||||||
|
asm volatile ("inb %w1, %b0": "=a" (data) : "Nd" (port));
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void outb(unsigned short port, unsigned char data)
|
||||||
|
{
|
||||||
|
asm volatile ("outb %b0, %w1" : : "a" (data), "Nd" (port));
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
static inline void outw(unsigned short port, unsigned short data)
|
||||||
|
{
|
||||||
|
asm volatile ("outw %w0, %w1" : : "a" (data), "Nd" (port));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void get_cpu_vendor_id(char *vendor_id) {
|
||||||
|
unsigned int eax, ebx, ecx, edx;
|
||||||
|
// Выполняем инструкцию CPUID с EAX = 0 для получения Vendor ID
|
||||||
|
eax = 0;
|
||||||
|
asm volatile (
|
||||||
|
"cpuid"
|
||||||
|
: "=b"(ebx), "=d"(edx), "=c"(ecx), "=a"(eax) // Выходные операнды
|
||||||
|
: "a"(eax) // Входной операнд, EAX = 0
|
||||||
|
);
|
||||||
|
|
||||||
|
// Копируем Vendor ID в строку
|
||||||
|
*((unsigned int *)&vendor_id[0]) = ebx;
|
||||||
|
*((unsigned int *)&vendor_id[4]) = edx;
|
||||||
|
*((unsigned int *)&vendor_id[8]) = ecx;
|
||||||
|
// Добавляем нуль-терминатор
|
||||||
|
vendor_id[12] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
//MOVE CURSORE TO POSITION
|
||||||
|
///////////////////////////////////////////////////////////////////////
|
||||||
|
void cursor_moveto(unsigned int strnum, unsigned int pos)
|
||||||
|
{
|
||||||
|
unsigned short new_pos = (strnum * VIDEO_WIDTH) + pos;
|
||||||
|
outb(CURSOR_PORT, 0x0F);
|
||||||
|
outb(CURSOR_PORT + 1, (unsigned char)(new_pos & 0xFF));
|
||||||
|
outb(CURSOR_PORT, 0x0E);
|
||||||
|
outb(CURSOR_PORT + 1, (unsigned char)((new_pos >> 8) & 0xFF));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Функция для получения времени
|
||||||
|
unsigned char get_time(unsigned char reg) {
|
||||||
|
|
||||||
|
outb(0x70, reg); // Записываем интересующий регистр в порт 0x70
|
||||||
|
return inb(0x71); // Читаем текущее значение из порта 0x71
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void curtime(char* buffer, unsigned int buffer_size) {
|
||||||
|
unsigned char seconds = get_time(0); // Читаем секунды
|
||||||
|
unsigned char minutes = get_time(2); // Читаем минуты
|
||||||
|
unsigned char hours = get_time(4); // Читаем часы
|
||||||
|
// Преобразуем BCD в десятичный формат
|
||||||
|
seconds = (seconds & 0x0F) + ((seconds >> 4) * 10);
|
||||||
|
minutes = (minutes & 0x0F) + ((minutes >> 4) * 10);
|
||||||
|
hours = ((hours & 0x0F) + ((hours >> 4) * 10) + 3) % 24;
|
||||||
|
// Формируем строку времени
|
||||||
|
char* ptr = buffer;
|
||||||
|
// Чаcы
|
||||||
|
*ptr++ = (hours / 10) + '0';
|
||||||
|
*ptr++ = (hours % 10) + '0';
|
||||||
|
*ptr++ = ':';
|
||||||
|
// Минуты
|
||||||
|
*ptr++ = (minutes / 10) + '0';
|
||||||
|
*ptr++ = (minutes % 10) + '0';
|
||||||
|
*ptr++ = ':';
|
||||||
|
// Секунды
|
||||||
|
*ptr++ = (seconds / 10) + '0';
|
||||||
|
*ptr++ = (seconds % 10) + '0';
|
||||||
|
// Завершаем строку
|
||||||
|
*ptr++ = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
void clear() {
|
||||||
|
|
||||||
|
unsigned char* video_buf = (unsigned char*)VIDEO_BUF_PTR;
|
||||||
|
// Очищаем весь видеобуфер
|
||||||
|
for (unsigned int i = 0; i < 80 * 25; i++) {
|
||||||
|
video_buf[i * 2] = (unsigned char)' '; // Установка пробела
|
||||||
|
}
|
||||||
|
|
||||||
|
// Сбрасываем курсор на начало
|
||||||
|
str_num = 0;
|
||||||
|
offset = 0;
|
||||||
|
cursor_moveto(str_num, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void get_str(char* ptr, int strnum)
|
||||||
|
{
|
||||||
|
unsigned char* video_buf = (unsigned char*)VIDEO_BUF_PTR;
|
||||||
|
video_buf += 80 * 2 * strnum;
|
||||||
|
|
||||||
|
for (int i = 0; i < 40; i++, video_buf += 2)
|
||||||
|
{
|
||||||
|
ptr[i] = *video_buf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_str(const char* ptr, unsigned int strnum);
|
||||||
|
|
||||||
|
void skip()
|
||||||
|
{
|
||||||
|
if (str_num != 25)
|
||||||
|
return;
|
||||||
|
char temp[41] = { 0 };
|
||||||
|
for (int i = 0; i < 24; i++)
|
||||||
|
{
|
||||||
|
get_str(temp, i + 1);
|
||||||
|
print_str(temp, i);
|
||||||
|
}
|
||||||
|
print_str(empty_str, 24);
|
||||||
|
str_num = 24;
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_str(const char* ptr, unsigned int strnum)
|
||||||
|
{
|
||||||
|
unsigned char* video_buf = (unsigned char*)VIDEO_BUF_PTR;
|
||||||
|
video_buf += 80 * 2 * strnum;
|
||||||
|
|
||||||
|
while (*ptr)
|
||||||
|
{
|
||||||
|
|
||||||
|
video_buf[0] = (unsigned char)*ptr;
|
||||||
|
video_buf[1] = CLR;
|
||||||
|
video_buf += 2;
|
||||||
|
ptr++;
|
||||||
|
}
|
||||||
|
|
||||||
|
str_num++; offset = 0;
|
||||||
|
skip();
|
||||||
|
cursor_moveto(str_num, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_char(char chr)
|
||||||
|
{
|
||||||
|
unsigned char* video_buf = (unsigned char*)VIDEO_BUF_PTR;
|
||||||
|
video_buf += 80 * 2 * str_num + offset * 2;
|
||||||
|
|
||||||
|
video_buf[0] = (unsigned char)chr;
|
||||||
|
video_buf[1] = CLR;
|
||||||
|
|
||||||
|
offset++;
|
||||||
|
cursor_moveto(str_num, offset);
|
||||||
|
}
|
||||||
|
//SHUTDOWN
|
||||||
|
////////////////////////////////////////////
|
||||||
|
void
|
||||||
|
shutdown_power_off (void)
|
||||||
|
{
|
||||||
|
const char s[] = "Shutdown";
|
||||||
|
const char *p;
|
||||||
|
|
||||||
|
str_num++;
|
||||||
|
offset = 0;
|
||||||
|
skip();
|
||||||
|
print_str("Powering off...", str_num);
|
||||||
|
outw (0xB004, 0x2000);
|
||||||
|
outw (0x604, 0x2000);
|
||||||
|
|
||||||
|
for (p = s; *p != '\0'; p++)
|
||||||
|
outb (0x8900, *p);
|
||||||
|
|
||||||
|
asm("cli");
|
||||||
|
asm("hlt");
|
||||||
|
}
|
||||||
|
///////////////////////////////////////////////
|
||||||
|
|
||||||
|
struct idt_entry
|
||||||
|
{
|
||||||
|
unsigned short base_lo;
|
||||||
|
unsigned short segm_sel;
|
||||||
|
unsigned char always0;
|
||||||
|
unsigned char flags;
|
||||||
|
unsigned short base_hi;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
|
||||||
|
struct idt_ptr
|
||||||
|
{
|
||||||
|
unsigned short limit;
|
||||||
|
unsigned int base;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
// Функция для преобразования ticks в строку
|
||||||
|
|
||||||
|
void uint_to_string(unsigned int num, char* str_ticks)
|
||||||
|
{
|
||||||
|
if (num == 0) {
|
||||||
|
str_ticks[0] = '0';
|
||||||
|
str_ticks[1] = '\0'; // Завершаем строку
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
char buffer[9 + 1]; // +1 для завершающего нуля
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
// Заполнение буфера цифрами в обратном порядке
|
||||||
|
while (num > 0) {
|
||||||
|
buffer[i++] = '0' + (num % 10); // Получаем последнюю цифру
|
||||||
|
num /= 10; // Убираем последнюю цифру
|
||||||
|
}
|
||||||
|
|
||||||
|
// Обратный порядок в строке
|
||||||
|
for (int j = 0; j < i; j++) {
|
||||||
|
str_ticks[j] = buffer[i - 1 - j];
|
||||||
|
}
|
||||||
|
str_ticks[i] = '\0'; // Завершаем строку
|
||||||
|
}
|
||||||
|
///////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void parseTime(char* timeStr, int* hours, int* minutes, int* seconds) {
|
||||||
|
*hours = (timeStr[0] - '0') * 10 + (timeStr[1] - '0');
|
||||||
|
*minutes = (timeStr[3] - '0') * 10 + (timeStr[4] - '0');
|
||||||
|
*seconds = (timeStr[6] - '0') * 10 + (timeStr[7] - '0');
|
||||||
|
}
|
||||||
|
|
||||||
|
void formatUptime(int totalSeconds, char* buffer) {
|
||||||
|
int hours = totalSeconds / 3600;
|
||||||
|
int minutes = (totalSeconds % 3600) / 60;
|
||||||
|
int seconds = totalSeconds % 60;
|
||||||
|
|
||||||
|
char* ptr = buffer;
|
||||||
|
|
||||||
|
// Форматируем часы
|
||||||
|
if (hours > 0) {
|
||||||
|
// Преобразуем часы в строку
|
||||||
|
if (hours >= 10) {
|
||||||
|
*ptr++ = (hours / 10) + '0';
|
||||||
|
*ptr++ = (hours % 10) + '0';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
*ptr++ = hours + '0';
|
||||||
|
}
|
||||||
|
|
||||||
|
*ptr++ = ' '; // Пробел после часов
|
||||||
|
|
||||||
|
// Добавляем "hour" или "hours"
|
||||||
|
if (hours == 1) {
|
||||||
|
*ptr++ = 'h';
|
||||||
|
*ptr++ = 'o';
|
||||||
|
*ptr++ = 'u';
|
||||||
|
*ptr++ = 'r';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
*ptr++ = 'h';
|
||||||
|
*ptr++ = 'o';
|
||||||
|
*ptr++ = 'u';
|
||||||
|
*ptr++ = 'r';
|
||||||
|
*ptr++ = 's';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Проверяем, нужны ли запятые
|
||||||
|
if (minutes > 0 || seconds > 0) {
|
||||||
|
*ptr++ = ',';
|
||||||
|
*ptr++ = ' ';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Форматируем минуты
|
||||||
|
if (minutes > 0) {
|
||||||
|
// Преобразуем минуты в строку
|
||||||
|
if (minutes >= 10) {
|
||||||
|
*ptr++ = (minutes / 10) + '0';
|
||||||
|
*ptr++ = (minutes % 10) + '0';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
*ptr++ = minutes + '0';
|
||||||
|
}
|
||||||
|
|
||||||
|
*ptr++ = ' '; // Пробел после минут
|
||||||
|
|
||||||
|
// Добавляем "minute" или "minutes"
|
||||||
|
if (minutes == 1) {
|
||||||
|
*ptr++ = 'm';
|
||||||
|
*ptr++ = 'i';
|
||||||
|
*ptr++ = 'n';
|
||||||
|
*ptr++ = 'u';
|
||||||
|
*ptr++ = 't';
|
||||||
|
*ptr++ = 'e';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
*ptr++ = 'm';
|
||||||
|
*ptr++ = 'i';
|
||||||
|
*ptr++ = 'n';
|
||||||
|
*ptr++ = 'u';
|
||||||
|
*ptr++ = 't';
|
||||||
|
*ptr++ = 'e';
|
||||||
|
*ptr++ = 's';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Проверяем, нужны ли запятые
|
||||||
|
if (seconds > 0) {
|
||||||
|
*ptr++ = ',';
|
||||||
|
*ptr++ = ' ';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Форматируем секунды
|
||||||
|
if (seconds >= 10) {
|
||||||
|
*ptr++ = (seconds / 10) + '0';
|
||||||
|
*ptr++ = (seconds % 10) + '0';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
*ptr++ = seconds + '0';
|
||||||
|
}
|
||||||
|
|
||||||
|
*ptr++ = ' '; // Пробел после секунд
|
||||||
|
|
||||||
|
// Добавляем "second" или "seconds"
|
||||||
|
if (seconds == 1) {
|
||||||
|
*ptr++ = 's';
|
||||||
|
*ptr++ = 'e';
|
||||||
|
*ptr++ = 'c';
|
||||||
|
*ptr++ = 'o';
|
||||||
|
*ptr++ = 'n';
|
||||||
|
*ptr++ = 'd';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
*ptr++ = 's';
|
||||||
|
*ptr++ = 'e';
|
||||||
|
*ptr++ = 'c';
|
||||||
|
*ptr++ = 'o';
|
||||||
|
*ptr++ = 'n';
|
||||||
|
*ptr++ = 'd';
|
||||||
|
*ptr++ = 's';
|
||||||
|
}
|
||||||
|
|
||||||
|
*ptr = '\0'; // Завершаем строку
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int calculateUptime(char* bootTime, char* currentTime, char* uptimeStr) {
|
||||||
|
int bootHours, bootMinutes, bootSeconds;
|
||||||
|
int currentHours, currentMinutes, currentSeconds;
|
||||||
|
|
||||||
|
parseTime(bootTime, &bootHours, &bootMinutes, &bootSeconds);
|
||||||
|
parseTime(currentTime, ¤tHours, ¤tMinutes, ¤tSeconds);
|
||||||
|
|
||||||
|
// Преобразуем всё в секунды
|
||||||
|
int bootTotalSeconds = bootHours * 3600 + bootMinutes * 60 + bootSeconds;
|
||||||
|
int currentTotalSeconds = currentHours * 3600 + currentMinutes * 60 + currentSeconds;
|
||||||
|
|
||||||
|
// Вычисляем общее время работы системы
|
||||||
|
int uptimeTotalSeconds = currentTotalSeconds - bootTotalSeconds;
|
||||||
|
|
||||||
|
// Если текущее время меньше времени включения (например, переход через полночь)
|
||||||
|
if (uptimeTotalSeconds < 0) {
|
||||||
|
uptimeTotalSeconds += 24 * 3600; // Добавляем 24 часа в секундах
|
||||||
|
}
|
||||||
|
|
||||||
|
formatUptime(uptimeTotalSeconds, uptimeStr);
|
||||||
|
return uptimeTotalSeconds;
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void meminfo_command()
|
||||||
|
{
|
||||||
|
unsigned int size = mem_h * 64 + mem_l;
|
||||||
|
char buffer[20];
|
||||||
|
uint_to_string(size, buffer);
|
||||||
|
print_str(buffer, str_num);
|
||||||
|
print_str("Kilobytes", str_num);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//VYPOLNENIYE COMMAND
|
||||||
|
////////////////////////////////////////////////////
|
||||||
|
void cmd_exec() {
|
||||||
|
int command_switch = 0;
|
||||||
|
|
||||||
|
if ('\0' == strncmp(command, "info", 4))
|
||||||
|
{
|
||||||
|
command_switch = 1;
|
||||||
|
}
|
||||||
|
else if ('\0' == strncmp(command, "help", 4))
|
||||||
|
{
|
||||||
|
command_switch = 2;
|
||||||
|
}
|
||||||
|
else if ('\0' == strncmp(command, "clear ", 5))
|
||||||
|
{
|
||||||
|
command_switch = 3;
|
||||||
|
}
|
||||||
|
else if ('\0' == strncmp(command, "curtime", 7))
|
||||||
|
{
|
||||||
|
command_switch = 4;
|
||||||
|
}
|
||||||
|
else if ('\0' == strncmp(command, "shutdown", 8))
|
||||||
|
{
|
||||||
|
command_switch = 5;
|
||||||
|
}
|
||||||
|
else if ('\0' == strncmp(command, "cpuid", 5))
|
||||||
|
{
|
||||||
|
command_switch = 6;
|
||||||
|
}
|
||||||
|
else if ('\0' == strncmp(command, "ticks", 5))
|
||||||
|
{
|
||||||
|
command_switch = 7;
|
||||||
|
}
|
||||||
|
else if ('\0' == strncmp(command, "loadtime", 8))
|
||||||
|
{
|
||||||
|
command_switch = 8;
|
||||||
|
}
|
||||||
|
else if ('\0' == strncmp(command, "uptime", 6))
|
||||||
|
{
|
||||||
|
command_switch = 9;
|
||||||
|
}
|
||||||
|
else if ('\0' == strncmp(command, "meminfo", 7))
|
||||||
|
{
|
||||||
|
command_switch = 10;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
command_switch = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (command_switch) {
|
||||||
|
case 1:
|
||||||
|
{
|
||||||
|
print_str("Made by ...", str_num);
|
||||||
|
print_str("...", str_num);
|
||||||
|
print_str("with: GNU Assembler, GCC, Intel syntax", str_num);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 2:
|
||||||
|
{
|
||||||
|
print_str("+ info - System information", str_num);
|
||||||
|
print_str("+ help - List of supported commands", str_num);
|
||||||
|
print_str("+ clear - Clear command history", str_num);
|
||||||
|
print_str("+ ticks - ticks number since the start", str_num);
|
||||||
|
print_str("+ loadtime - The time the OS was booted", str_num);
|
||||||
|
print_str("+ curtime - Current time", str_num);
|
||||||
|
print_str("+ uptime - Uptime in a readable format", str_num);
|
||||||
|
print_str("+ meminfo - Inf about available memory", str_num);
|
||||||
|
print_str("+ cpuid - Specifies the processor model", str_num);
|
||||||
|
print_str("+ shutdown - Computer shutdown", str_num);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 3:
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 4:
|
||||||
|
{
|
||||||
|
char time_str[50]; // Буфер для строки времени
|
||||||
|
curtime(time_str, sizeof(time_str));
|
||||||
|
print_str(time_str, str_num);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 5:
|
||||||
|
{
|
||||||
|
shutdown_power_off();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 6:
|
||||||
|
{
|
||||||
|
char vendor_id[13];
|
||||||
|
get_cpu_vendor_id(vendor_id);
|
||||||
|
print_str(vendor_id, str_num);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 7:
|
||||||
|
{
|
||||||
|
char str_ticks[10];
|
||||||
|
uint_to_string(ticks, str_ticks);
|
||||||
|
print_str(str_ticks, str_num);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 8:
|
||||||
|
{
|
||||||
|
print_str(time_os_loaded, str_num);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 9:
|
||||||
|
{
|
||||||
|
char currentTime[50]; // Буфер для строки времени
|
||||||
|
curtime(currentTime, sizeof(currentTime));
|
||||||
|
char uptimeStr[100]; // Буфер для строки uptime
|
||||||
|
calculateUptime(time_os_loaded, currentTime, uptimeStr);
|
||||||
|
print_str(uptimeStr, str_num);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 10:
|
||||||
|
{
|
||||||
|
meminfo_command();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
print_str("wrong input", str_num);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
//NAZHATIE KLAVISH
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void on_key(unsigned int scan_code)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < 43; i++)
|
||||||
|
{
|
||||||
|
if (scan_code == kbd_scan[i])
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (i == 43)
|
||||||
|
return;
|
||||||
|
if (i >= 0 && i <= 25)
|
||||||
|
{
|
||||||
|
if (is_shift_pressed == true)
|
||||||
|
{
|
||||||
|
command[offset] = alphabet[i] - (char)0x20;
|
||||||
|
print_char(alphabet[i] - (char)0x20);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
command[offset] = alphabet[i];
|
||||||
|
print_char(alphabet[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (i >= 26 && i <= 29)
|
||||||
|
{
|
||||||
|
command[offset] = alphabet[i];
|
||||||
|
print_char(alphabet[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (i == 30)
|
||||||
|
{
|
||||||
|
str_num++;
|
||||||
|
skip();
|
||||||
|
offset = 0;
|
||||||
|
cursor_moveto(str_num, offset);
|
||||||
|
cmd_exec();
|
||||||
|
for (int i = 0; i < 41; i++)
|
||||||
|
command[i] = '\0';
|
||||||
|
str_num++;
|
||||||
|
skip();
|
||||||
|
offset = 0;
|
||||||
|
cursor_moveto(str_num, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (i >= 31 && i <= 40)
|
||||||
|
{
|
||||||
|
if (is_shift_pressed)
|
||||||
|
{
|
||||||
|
command[offset] = '*';
|
||||||
|
print_char('*');
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char num = (char)((kbd_scan[i] - 1) % 10 + '0');
|
||||||
|
command[offset] = num - '0';
|
||||||
|
print_char(num);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (offset == 0)
|
||||||
|
return;
|
||||||
|
offset--;
|
||||||
|
command[offset] = '\0';
|
||||||
|
print_char(' ');
|
||||||
|
offset--;
|
||||||
|
cursor_moveto(str_num, offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//SCHITIVANIE POSTUPAYSHEGO SIMVOLA
|
||||||
|
//////////////////////////////////////////////////////////
|
||||||
|
void process_shift(unsigned int scan_code)
|
||||||
|
{
|
||||||
|
if (scan_code == kbd_scan[42])
|
||||||
|
{
|
||||||
|
is_shift_pressed = true;
|
||||||
|
}
|
||||||
|
else if (scan_code == kbd_scan[43])
|
||||||
|
{
|
||||||
|
is_shift_pressed = false;
|
||||||
|
}
|
||||||
|
else if (scan_code < 128 || scan_code == 0x135)
|
||||||
|
{
|
||||||
|
on_key(scan_code);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void keyb_process_keys()
|
||||||
|
{
|
||||||
|
if (inb(0x64) & 0x01)
|
||||||
|
{
|
||||||
|
unsigned int scan_code;
|
||||||
|
scan_code = (unsigned int)inb(0x60) & 0x1FF;
|
||||||
|
|
||||||
|
if (offset == 40 && scan_code != kbd_scan[30])
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
process_shift(scan_code);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
//OBRABOTCHIK PRERIVANIY
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void keyb_handler()
|
||||||
|
{
|
||||||
|
asm("pusha");
|
||||||
|
keyb_process_keys();
|
||||||
|
outb(PIC1_PORT, 0x20);
|
||||||
|
asm("popa; leave; iret");
|
||||||
|
}
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
// Обработчик тиков
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void timer_handler()
|
||||||
|
{
|
||||||
|
asm("pusha");
|
||||||
|
ticks++; // Инкрементируем счетчик тиков
|
||||||
|
outb(PIC1_PORT, 0x20); // Посылаем сигнал завершения прерывания
|
||||||
|
asm("popa; leave; iret");
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
//PROCEDURA OBRABOTCHIK PRERIVANIY
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
struct idt_entry g_idt[256];
|
||||||
|
struct idt_ptr g_idtp;
|
||||||
|
void default_interrupt_handler()
|
||||||
|
{
|
||||||
|
asm("pusha");
|
||||||
|
asm("popa; leave; iret");
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef void(*interrupt_handler)();
|
||||||
|
void interrupt_reg_handler(int num, unsigned short segm_sel, unsigned short
|
||||||
|
flags, interrupt_handler hndlr)
|
||||||
|
{
|
||||||
|
unsigned int hndlr_addr = (unsigned int)hndlr;
|
||||||
|
|
||||||
|
g_idt[num].base_lo = (unsigned short)(hndlr_addr & 0xFFFF);
|
||||||
|
g_idt[num].segm_sel = segm_sel;
|
||||||
|
g_idt[num].always0 = 0;
|
||||||
|
g_idt[num].flags = flags;
|
||||||
|
g_idt[num].base_hi = (unsigned short)(hndlr_addr >> 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
void keyb_init()
|
||||||
|
{
|
||||||
|
interrupt_reg_handler(0x09, GDT_CS, 0x80 | IDT_TYPE_INTR, keyb_handler);
|
||||||
|
outb(PIC1_PORT + 1, 0xFF ^ 0x02);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void timer_init()
|
||||||
|
{
|
||||||
|
// Регистрация обработчика прерывания
|
||||||
|
interrupt_reg_handler(8, GDT_CS, 0x80 | IDT_TYPE_INTR, timer_handler);
|
||||||
|
// segm_sel=0x8, P=1, DPL=0, Type=Intr
|
||||||
|
|
||||||
|
// Разрешение только прерываний клавиатуры от контроллера 8259
|
||||||
|
outb(PIC1_PORT + 1, 0xFF ^ 0x01); // 0xFF - все прерывания, 0x02 - бит IRQ1 (клавиатура)
|
||||||
|
// Разрешены будут только прерывания, чьи биты установлены в 0
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void interrupt_init()
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int idt_count = sizeof(g_idt) / sizeof(g_idt[0]);
|
||||||
|
|
||||||
|
for (i = 0; i < idt_count; i++)
|
||||||
|
interrupt_reg_handler(i, GDT_CS, 0x80 | IDT_TYPE_INTR,
|
||||||
|
default_interrupt_handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
void interrupt_start()
|
||||||
|
{
|
||||||
|
int idt_count = sizeof(g_idt) / sizeof(g_idt[0]);
|
||||||
|
|
||||||
|
g_idtp.base = (unsigned int)(&g_idt[0]);
|
||||||
|
g_idtp.limit = (sizeof(struct idt_entry) * idt_count) - 1;
|
||||||
|
|
||||||
|
asm("lidt %0" : : "m" (g_idtp));
|
||||||
|
}
|
||||||
|
|
||||||
|
void interrupt_enable()
|
||||||
|
{
|
||||||
|
asm("sti");
|
||||||
|
}
|
||||||
|
|
||||||
|
void interrupt_disable()
|
||||||
|
{
|
||||||
|
asm("cli");
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" int kmain()
|
||||||
|
{
|
||||||
|
interrupt_init();
|
||||||
|
timer_init();
|
||||||
|
interrupt_disable();
|
||||||
|
keyb_init();
|
||||||
|
interrupt_start();
|
||||||
|
interrupt_enable();
|
||||||
|
cursor_moveto(str_num, offset);
|
||||||
|
|
||||||
|
curtime(time_os_loaded, sizeof(time_os_loaded));
|
||||||
|
|
||||||
|
char m1, m2;
|
||||||
|
m1 = (*(char*)(0x3400));
|
||||||
|
m2 = (*(char*)(0x3420));
|
||||||
|
mem_l = (unsigned short)m1;
|
||||||
|
mem_h = (unsigned short)m2;
|
||||||
|
|
||||||
|
const char* hello = ".:: WELCOME TO INFO_OS ::.";
|
||||||
|
print_str(hello , str_num);
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
outb(PIC1_PORT + 1, 0xFF ^ 0x02);
|
||||||
|
outb(PIC1_PORT + 1, 0xFF ^ 0x01);
|
||||||
|
asm("hlt");
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue