Notes on 30 days self made operating system - Day6

Posted by Griffin on Fri, 28 Jan 2022 13:51:02 +0100

Segment properties:

void set_segmdesc(struct SEGMENT_DESCRIPTOR *sd, unsigned int limit, int base,
int ar)
{
if (limit > 0xfffff) {
ar |= 0x8000; /* G_bit = 1 */
limit /= 0x1000;
}
sd->limit_low = limit & 0xffff;
sd->base_low = base & 0xffff;
sd->base_mid = (base >> 16) & 0xff;
sd->access_right = ar & 0xff;
sd->limit_high = ((limit >> 16) & 0x0f) | ((ar >> 8) & 0xf0);
sd->base_high = (base >> 24) & 0xff;
return;
}

In this structure, the base is divided into three segments: low (2 bytes), mid (1 byte) and high (1 byte), which together are just 32 bits Segment upper limit. It indicates how many bytes a segment has. However, there is a problem here. The maximum segment limit is 4GB, that is, a 32-bit value. If you put it directly, the value itself will occupy 4 bytes, plus the base address, a total of 8 bytes, which will fill the whole structure. In this way, there is no place to save the management attribute information of the segment, which is not possible. Therefore, the segment upper limit can only use 20 bits. In this way, the maximum segment limit can only be specified to 1MB. There are 4GB, but only 1MB can be used It's a sad illusion that we're back to the age of 16. Here, Intel's uncles came up with another way. They set a flag bit called Gbit in the segment properties. When this flag bit is 1, the unit of limit is not interpreted as byte, but as page. What is the page? In the computer CPU, 1 page refers to 4KB. As a result, 4KB × 1M = 4GB, so 4GB segments can be specified. Finally, I can rest assured. By the way, "g" of G bit is the abbreviation of "granularity", which refers to the size of the unit.

PIC:programmable interrupt controller
PIC is a device that integrates 8 interrupt signals into one interrupt signal. PIC monitors the eight interrupt signals of the input pin. As long as one interrupt signal comes in, it turns the only output pin signal ON and notifies the CPU. IBM's uncles wanted to process more interrupt signals by adding PIC. They thought that the computer would have more than 8 external devices, so they designed 15 interrupt signals and added 2 PIC for this purpose. (the PIC directly connected to the CPU is called the master PIC, and the PIC connected to the master PIC is called the slave PIC. The main PIC is responsible for processing interrupt signals 0 to 7, and the slave PIC is responsible for processing interrupt signals 8 to 15)

code:
int.c Main components of
void init_pic(void)
/* PIC Initialization of */
{
io_out8(PIC0_IMR, 0xff ); /* Disable all interrupts */
io_out8(PIC1_IMR, 0xff ); /* Disable all interrupts */
io_out8(PIC0_ICW1, 0x11 ); /* edge trigger mode */
io_out8(PIC0_ICW2, 0x20 ); /* IRQ0-7 Received by INT20-27 */
io_out8(PIC0_ICW3, 1 << 2); /* PIC1 Connected by IRQ2 */
io_out8(PIC0_ICW4, 0x01 ); /* No buffer mode */
io_out8(PIC1_ICW1, 0x11 ); /* edge trigger mode */
io_out8(PIC1_ICW2, 0x28 ); /* IRQ8-15 Received by INT28-2f */
io_out8(PIC1_ICW3, 2 ); /* PIC1 Connected by IRQ2 */
io_out8(PIC1_ICW4, 0x01 ); /* No buffer mode */
io_out8(PIC0_IMR, 0xfb ); /* 11111011 PIC1 All except */
io_out8(PIC1_IMR, 0xff ); /* 11111111 Disable all interrupts */
return;
}

PIC register:
The 8 bits of IMR(interrupt mask register) correspond to 8 IRQ signals respectively. If a channel is 1, the IRQ signal of this bit is shielded, and the PIC ignores this channel signal. (refer to the book for specific reasons)
ICW (initial control word) there are 4 ICWS, numbered 1 ~ 4 respectively, with 4 bytes of data. (ICW1 and ICW4 are related to the wiring mode of PIC mainboard and the electrical characteristics of interrupt signal. ICW3 is the setting of master-slave connection. For the master pic, the IRQ number is connected with the slave pic and is set with 8 bits. ICW2 determines which interrupt IRQ informs the CPU)

More importantly, INT 0x20-0x2f 15 is not used because when some programs want to destroy the operating system, the CPU will automatically generate INT 0x00~0x1f. If these are repeated with IRQ, the CPU will not know whether it is IRQ or the system protection notification of CPU.

The mouse is IRQ12 and the keyboard is IRQ1, so the interrupt handler of INT 0x2c and INT 0x21 should be written.

void inthandler21(int *esp)
/* Interrupt from PS/2 keyboard */
{
struct BOOTINFO *binfo = (struct BOOTINFO *) ADR_BOOTINFO;
boxfill8(binfo->vram, binfo->scrnx, COL8_000000, 0, 0, 32 * 8 - 1, 15);
putfonts8_asc(binfo->vram, binfo->scrnx, 0, 0, COL8_FFFFFF, "INT 21 (IRQ-1) :
PS/2 keyboard");
for (;;) {
io_hlt();
}
}

Since the interrupt processing is completed, the "return" (RET instruction) cannot be executed, but the IRETD instruction must be executed (it cannot be written in C language, so the assembly file must be modified)

EXTERN _inthandler21, _inthandler2c
_asm_inthandler21:
PUSH ES
PUSH DS
PUSHAD
MOV EAX,ESP
PUSH EAX
MOV AX,SS
MOV DS,AX
MOV ES,AX
CALL _inthandler21
POP EAX
POPAD
POP DS
POP ES
IRETD

This function only saves the value of the register to the stack, then adjusts DS and ES to be equal to SS, and then calls_ inthandler21 (so you have to modify the function in naskfun.nas). After returning, return the values of all registers to the original values, and then execute IRETD.

Secondly, register this function in IDT.

/* IDT Setting of */
set_gatedesc(idt + 0x21, (int) asm_inthandler21, 2 * 8, AR_INTGATE32);
set_gatedesc(idt + 0x2c, (int) asm_inthandler2c, 2 * 8, AR_INTGATE32);

2 * 8 here represents ASM_ Which segment does inthandler21 belong to, that is, the segment number is 2, multiplied by 8 because the lower 3 digits have other meanings. Here, the lower 3 digits must be 0. "2 * 8" can also be written as "2 < < 3"

PS:
about PUSH EAX Instruction (analogy to):
ADD ESP,-4
MOV [SS:ESP],EAX
ESP Subtract 4 from the value of the address, take the obtained result as the address value, and save the value in the register to the memory corresponding to the address.
about POP EAX Instruction (analogy to):
MOV EAX,[SS:ESP]
ADD ESP,4

PUSHAD amount to:
PUSH EAX
PUSH ECX
PUSH EDX
PUSH EBX
PUSH ESP
PUSH EBP
PUSH ESI
PUSH EDI   and POPAD The instructions are equivalent to the reverse order above.

Topics: Operating System