Добавил 2-ю лабу по осям за 4 сем

master
serr 2024-11-12 12:38:49 +03:00
parent cdb9116713
commit 15671d75a8
2 changed files with 990 additions and 0 deletions

View File

@ -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

View File

@ -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;
// Ча
*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, &currentHours, &currentMinutes, &currentSeconds);
// Преобразуем всё в секунды
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;
}