[OS]miniOS-Text-3

๐Ÿ‘‰๐Ÿป miniOS-Text-3์—์„œ๋Š” ํ™”๋ฉด ์Šคํฌ๋กค๊ณผ ํ•˜๋“œ์›จ์–ด ์ปค์„œ์ œ์–ด ๊ตฌํ˜„์ž…๋‹ˆ๋‹ค.
miniOS-Text-3 implements screen scrolling and hardware cursor control.

๐Ÿ“ ์ฝ”๋“œ / Code

โœ”๏ธ I/O ํฌํŠธ ์ œ์–ด ํ•จ์ˆ˜ / I/O port control functions

static inline void outb(word port, byte value) {
    __asm__ __volatile__("outb %0, %1" : : "a"(value), "Nd"(port));
}

1)VGA๊ทธ๋ž˜ํ”ฝ,ํ‚ค๋ณด๋“œ,๋งˆ์šฐ์Šค,PC์Šคํ”ผ์ปค ์ผ๋ถ€๊ธฐ๋Šฅ ์ œ์–ด๋ฅผ ์œ„ํ•ด์„œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
It is used to control certain functions of the VGA graphics, keyboard, mouse, and PC speakers.

โœ”๏ธ ์Šคํฌ๋กค ํ•จ์ˆ˜ / Scroll function

1) 0๋ฒˆ์งธ ์ค„์„ 1๋ฒˆ ์ค„๋กœ ์˜ฌ๋ฆฌ๊ณ  ํ™”๋ฉด์˜ ๊ฐ€์žฅ ์œ„์ชฝ 25๋ฒˆ์ค„์€ 24๋ฒˆ์ค„๋กœ ๋ฎ์–ด์“ฐ๊ธฐ
Shift line 0 up to line 1, and overwrite line 25โ€”at the very top of the screenโ€”with the contents of line 24.

    for (int i = 0; i < 24 * 80; i++) {
        vram[i] = vram[i + 80];
    }

A.์ง€๊ธˆ ํ™”๋ฉดํ•ด์ƒ๋„๋Š” ๊ฐ€๋กœ 80๊ธ€์ž ์„ธ๋กœ 25์ค„์ž…๋‹ˆ๋‹ค.(0~24 = 25์ค„)
The current screen resolution is 80 characters wide by 25 lines high (0~24 = 25 lines).

B. vram[i + 80]๋Š” ๋ณต์‚ฌํ•  ๊ฐ’์˜ ์œ„์น˜๊ฐ€ ๋‹ค์Œ ์ค„์˜ ๋™์ผํ•œ ์œ„์น˜์ž„์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.
vram[i + 80] means that the location of the value to be copied is at the same position on the next line.

C.์ฆ‰ i = 80์ด๋ฉด 1๋ฒˆ ์ค„์˜ ๋งจ ์ฒซ ๊ธ€์ž์œ„์น˜(vram[80])์— 2๋ฒˆ ์ค„์˜ ๋งจ ์ฒซ ๊ธ€์ž( vram[160])๊ฐ’์„ ๋ณต์‚ฌํ•ด์„œ ๋„ฃ์Šต๋‹ˆ๋‹ค.
In other words, if i = 80, the value of the first character of the second row (vram[160]) is copied into the position of the first character of the first row (vram[80]).

D.์ด๋ ‡๊ฒŒํ•˜๋ฉด ํ™”๋ฉด์˜ ๊ฐ€์žฅ ์œ„์ชฝ ์ค„์ธ 0๋ฒˆ์ค„์€ 1๋ฒˆ์ค„๋กœ ๋ฎ์–ด์“ฐ๊ธฐ ๋˜๊ณ  ๊ฐ€์žฅ ์•„๋žซ์ค„ 24๋ฒˆ์ค„์€ 23๋ฒˆ์ค„๋กœ ํ•œ ์นธ ์˜ฌ๋ผ์˜ค๊ฒŒ๋ฉ๋‹ˆ๋‹ค.
By doing this, row 0โ€”the topmost row on the screenโ€”is overwritten by row 1, while row 24โ€”the bottommost rowโ€”shifts up by one position, taking the place of row 23.

2)24๋ฒˆ์ค„์˜ ๊ธฐ์กด ๋ฐ์ดํ„ฐ๋ฅผ ์‚ญ์ œํ•˜๊ธฐ
Delete the existing data in row 24

    for (int i = 24 * 80; i < 25 * 80; i++) {
        vram[i] = (0x0F << 8) | ' '; 
    }

A.i์˜ ์‹œ์ž‘๊ฐ’์ด 23๋ฒˆ์งธ ์ค„ ๋ ๋ถ€ํ„ฐ ์‹œ์ž‘ํ•ด์„œ 24๋ฒˆ์งธ ์ค„ ๋๊นŒ์ง€ ํ•œ๊ธ€์ž์”ฉ ๊ธ€์ž์ง€์šฐ๊ธฐ ๋ฐ˜๋ณต
The initial value of i begins from the end of the 23rd line and proceeds through the end of the 24th line, with characters being deleted one by one in a repeating process.

B.๋น„ํŠธ์—ฐ์‚ฐ(OR ์—ฐ์‚ฐ) / Bitwise operation (OR operation)

  0000 1111 0000 0000  (0x0F๊ฐ€ ์™ผ์ชฝ์œผ๋กœ 8์นธ ์ด๋™ํ•œ ๊ฐ’ / The value of 0x0F moved 8 spaces to the left)
| 0000 0000 0010 0000  (๊ณต๋ฐฑ ๋ฌธ์ž/Whitespace character ' ' = 0x20)
----------------------
  0000 1111 0010 0000  (์ตœ์ข… 16๋น„ํŠธ ์™„์„ฑ / Final 16-bit version complete)

a)0x0F = 15 = 0000 1111 ์ด๋ฉฐ ์™ผ์ชฝ์œผ๋กœ 8๋น„ํŠธ ๋ฐ€๋ฉด 1111 0000 0000์ด ๋ฉ๋‹ˆ๋‹ค.
0x0F = 15 = 0000 1111; shifting it 8 bits to the left results in 1111 0000 0000.

b)0x20 = 32 = 0010 0000

c)์ตœ์ข…์ ์œผ๋กœ 16๋น„ํŠธ ๊ฐ’์€ 0000 1111 0010 0000 ์ด ๋ฉ๋‹ˆ๋‹ค.
Ultimately, the 16-bit value becomes 0000 1111 0010 0000.

d)0000 1111 0010 0000 = 0x0F20 ์ด๊ณ  0x0F์€ ์ƒ์œ„๋ฐ”์ดํŠธ 0x20์€ ํ•˜์œ„๋ฐ”์ดํŠธ์ž…๋‹ˆ๋‹ค.
0000 1111 0010 0000 = 0x0F20, where 0x0F is the high byte and 0x20 is the low byte.

e)์ƒ์œ„ ๋ฐ”์ดํŠธ์—๋Š” ๊ธ€์ž๋Š” ํฐ์ƒ‰ ๋ฐฐ๊ฒฝ์€ ๊ฒ€์€์ƒ‰์ž„์„ ์˜๋ฏธํ•˜๊ณ  ํ•˜์œ„๋ฐ”์ดํŠธ๋Š” ๊ณต๋ฐฑ์ž„์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.
The upper byte indicates that the characters are white on a black background, while the lower byte represents a space.

f)varm[i]์ฆ‰ ๋งˆ์ง€๋ง‰ ์ค„์—๋Š” 2์ง„์ˆ˜ ๊ฐ’์ด ๋“ค์–ด๊ฐ€๊ณ  ์ƒ์œ„๋ฐ”์ดํŠธ์™€ ํ•˜์œ„๋ฐ”์ดํŠธ๋ฅผ ์†์„ฑ์œผ๋กœ ๋น„๋””์˜ค ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ์ธ์‹ํ•ฉ๋‹ˆ๋‹ค.
In the final lineโ€”varm[i]โ€”a binary value is stored, and the video memory interprets this by treating the data as consisting of an upper byte and a lower byte.

g)ํ•ต์‹ฌ์€ VGA ํ•˜๋“œ์›จ์–ด๊ฐ€ ๋น„๋””์˜ค ๋ฉ”๋ชจ๋ฆฌ(0xB8000)์˜ 16๋น„ํŠธ(2๋ฐ”์ดํŠธ) ๊ณต๊ฐ„์„ ๋ฐ˜์œผ๋กœ ๋‚˜๋ˆ„์–ด์„œ ์ƒ์œ„๋ฐ”์ดํŠธ๋Š” ์†์„ฑ์œผ๋กœ ์ธ์‹ํ•˜๊ณ  ํ•˜์œ„๋ฐ”์ดํŠธ๋Š” ๋ฌธ์ž๋กœ ์ธ์‹ํ•œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
The key point is that the VGA hardware divides each 16-bit (2-byte) unit of video memory (starting at 0xB8000) into two halves: the upper byte is interpreted as an attribute, while the lower byte is interpreted as a character.

โœ”๏ธ ์ปค์„œ ์œ„์น˜ ์…‹ํŒ…ํ•˜๋Š” ํ•จ์ˆ˜
A function that sets the cursor position

void update_cursor(int x, int y) {
    // ํ™”๋ฉด์€ ๊ฐ€๋กœ 80๊ธ€์ž, ์„ธ๋กœ 25์ค„์ด๋ฏ€๋กœ ์ „์ฒด ์œ„์น˜(์˜คํ”„์…‹) ๊ณ„์‚ฐ
    // Since the screen is 80 characters wide and 25 lines high, calculate the total position (offset)
    unsigned short cursorLocation = y * 80 + x;

    // 1. ์ปค์„œ ์œ„์น˜์˜ 'ํ•˜์œ„ 8๋น„ํŠธ'๋ฅผ ์„ค์ •ํ•˜๊ธฐ ์œ„ํ•ด ์ธ๋ฑ์Šค 0x0F ์„ ํƒ
    // Select index 0x0F to set the 'lower 8 bits' of the cursor position.
    outb(0x3D4, 0x0F);
    outb(0x3D5, (unsigned char)(cursorLocation & 0xFF));

    // 2. ์ปค์„œ ์œ„์น˜์˜ '์ƒ์œ„ 8๋น„ํŠธ'๋ฅผ ์„ค์ •ํ•˜๊ธฐ ์œ„ํ•ด ์ธ๋ฑ์Šค 0x0E ์„ ํƒ
    // Select index 0x0E to set the 'upper 8 bits' of the cursor position
    outb(0x3D4, 0x0E);
    outb(0x3D5, (unsigned char)((cursorLocation >> 8) & 0xFF));
}

1)ํ˜„์žฌ ์ปค์„œ๊ฐ€ ๋ช‡๋ฒˆ์งธ ์นธ์— ์žˆ๋Š”์ง€ ๊ณ„์‚ฐ ํ•˜๊ธฐ
Calculate the current cursor position

unsigned short cursorLocation = y * 80 + x;

2)VGA ์ธ๋ฑ์Šค(์ฃผ์†Œ) ํฌํŠธ(0x3D4)์— 0x0F(=15)๊ฐ’ ์…‹ํŒ…( 0x0F๋Š” ํ•˜์œ„๋น„ํŠธ ์…‹ํŒ…์„ ์˜๋ฏธํ•จ)
Set the value 0x0F (=15) in the VGA index (address) port (0x3D4) (0x0F signifies the setting of the lower bits).

outb(0x3D4, 0x0F);

3)์œ„์—์„œ ์„ค์ •๋œ ์ฃผ์†Œ์— ์‹ค์ œ๋กœ ๊ฐ’์„ ํ• ๋‹น
Actually assign a value to the address set above

outb(0x3D5, (unsigned char)(cursorLocation & 0xFF));

A.0xFF์˜ ์›๋ž˜๋Š” 0x00FF ํ˜•ํƒœ์ด์ง€๋งŒ ๋ณดํ†ต ์•ž์˜ 00์„ ์ƒ๋žตํ•ฉ๋‹ˆ๋‹ค.
While 0xFF is technically in the form 0x00FF, the leading 00 is typically omitted.

B. ์ด์ง„์ˆ˜๋กœ ํ‘œํ˜„ํ•˜๋ฉด 0000 0000 1111 1111์ด ๋ฉ๋‹ˆ๋‹ค.
When expressed in binary, it becomes 0000 0000 1111 1111.

C.ํ•˜์œ„๋น„ํŠธ๋งŒ ์ฑ„์›Œ์ง„ ๊ฐ’์ด๊ณ  ๋‚˜์ค‘์— ์ด ํ•˜์œ„๋น„ํŠธ๋งŒ ๋”ฐ๋กœ ๋ฝ‘์•„์„œ ์‚ฌ์šฉ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
This value contains data only in the lower bits, and these lower bits can be extracted and used separately later.

D. cursorLocation๊ณผ 0xFF๋ฅผ ๋น„ํŠธ์—ฐ์‚ฐ(AND ์—ฐ์‚ฐ)
Perform a bitwise AND operation on cursorLocation with 0xFF.

0000 0001 0101 1010  (cursorLocation = 0x015A)
& 0000 0000 1111 1111  (0xFF)
---------------------
  0000 0000 0101 1010  

๊ฒฐ๊ณผ: ์•ž์˜ ์ƒ์œ„ 8๋น„ํŠธ๋Š” 0์œผ๋กœ ๋‚ ์•„๊ฐ€๊ณ , ๋’ค์˜ ํ•˜์œ„ 8๋น„ํŠธ์ธ 0x5A๋งŒ ๋‚จ์Œ
Result: The first upper 8 bits are discarded as 0, and only the latter lower 8 bits, 0x5A, remain.

AND์—ฐ์‚ฐ์œผ๋กœ ์ƒ์œ„๋น„ํŠธ๋Š” 0์œผ๋กœ ๋งŒ๋“ค๊ณ  ํ•˜์œ„๋น„ํŠธ๋Š” ๊ทธ๋Œ€๋กœ ์œ ์ง€ํ•ฉ๋‹ˆ๋‹ค.
Using an AND operation, the upper bits are set to 0, while the lower bits are kept as they are.

๐Ÿ’ก AND์—ฐ์‚ฐ์˜ ๋ชฉ์  / Purpose of the AND operation

1.ํ•„์š”ํ•œ ๋ถ€๋ถ„๋งŒ ๋‚จ๊ธฐ๊ณ  ๋‚˜๋จธ์ง€๋ฅผ ์ง€์šฐ๋Š” '๋งˆ์Šคํฌ ์ž‘์—…'
'Masking'โ€”a process of keeping only the necessary parts and erasing the rest

2.ํŠน์ • ๋น„ํŠธ์˜ ์ƒํƒœ๋ฅผ ํ™•์ธํ•˜๋Š” '์ถ”์ถœ ์ž‘์—…
An 'extraction operation' that checks the state of a specific bit

4)VGA ์ธ๋ฑ์Šค(์ฃผ์†Œ) ํฌํŠธ(0x3D4)์— 0x0E(=14)๊ฐ’ ์…‹ํŒ…( 0x0E๋Š” ์ƒ์œ„๋น„ํŠธ ์…‹ํŒ…์„ ์˜๋ฏธํ•จ)
Set the value 0x0E (14) in the VGA index (address) port (0x3D4) โ€” 0x0E signifies the setting of the high-order bits.

 outb(0x3D4, 0x0E);

5)์œ„์—์„œ ์„ค์ •๋œ ์ฃผ์†Œ์— ์‹ค์ œ๋กœ ๊ฐ’์„ ํ• ๋‹น
Actually assign a value to the address set above

  outb(0x3D5, (unsigned char)((cursorLocation >> 8) & 0xFF));

A.(cursorLocation >> 8) & 0xFF)

1. ์šฐ์ธก์œผ๋กœ 8๋น„ํŠธ ์ด๋™ / Shift 8 bits to the right

AND operation with 0xFF
0000 0001 0101 1010  (cursorLocation = 0x015A)
--------------------- (>> 8๋น„ํŠธ ์šฐ์ธก์œผ๋กœ ์ด๋™ / Shift 8 bits to the right)
0000 0000 0000 0001  
๊ฒฐ๊ณผ: ์ƒ์œ„ ๋ฐ”์ดํŠธ์˜€๋˜ 0x01์ด ์•„๋ž˜๋กœ ๋‚ด๋ ค์˜ด
Result: 0x01, which was the upper byte, has moved down.

2.0xFF์™€ AND์—ฐ์‚ฐ / AND operation with 0xFF

  0000 0000 0000 0001  (8๋น„ํŠธ ์šฐ์ธก์ด๋™ํ•œ ๊ฐ’ / Value shifted 8 bits to the right)
& 0000 0000 1111 1111  (0xFF ๋งˆ์Šคํฌ / 0xFF mask)
---------------------
  0000 0000 0000 0001  ๊ฒฐ๊ณผ/result: 0x01
๐Ÿ’ก 8๋น„ํŠธ ์šฐ์ธก ์ด๋™๋งŒํ•ด๋„ ์ƒ์œ„๋น„ํŠธ๋Š” 0๋งŒ ์กด์žฌํ•˜์ง€๋งŒ AND์—ฐ์‚ฐ์„ ํ†ตํ•ด์„œ 
   ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ์˜ˆ์™ธ์‚ฌํ•ญ์˜ ๋ฐœ์ƒ์„ ๋ง‰์•„ ์ค๋‹ˆ๋‹ค.

Even though an 8-bit right shift results in zeros in the upper bits, an AND operation is used to prevent any potential exceptions that might otherwise occur.

โœ”๏ธ kernel_main ํ•จ์ˆ˜/function

                 // โœ… miniOS-Text-3
                 // ํ™”๋ฉด์„ ๊ฝ‰ ์ฑ„์› ๋Š”์ง€ ๊ฒ€์‚ฌ (25์ค„ * 80๊ธ€์ž = 2000)
                 // Check if the screen is completely filled (25 lines * 80 characters = 2000)
                    if (cursor >= 2000) {
                        // ์Šคํฌ๋กค ํ›„ ๊ฐฑ์‹ ๋œ ์ปค์„œ ์œ„์น˜๋ฅผ ๋‹ค์‹œ ๋ฐ›์•„์˜ด
                        // Retrieve the updated cursor position after scrolling
                        cursor = scroll_screen(); 
                    }
                    
                    // โœ… miniOS-Text-3
                    // ์ปค์„œ ์ขŒํ‘œ ๊ณ„์‚ฐํ•ด์„œ ํ•˜๋“œ์›จ์–ด ์ปค์„œ ์—…๋ฐ์ดํŠธ 
                    // Calculate cursor coordinates and update the hardware cursor
                    // (x = cursor % 80, y = cursor / 80)
                    update_cursor(cursor % 80, cursor / 80);

A.25 * 80 = 2000 , ๊ธ€์ž์ž…๋ ฅ์ด ์ „์ฒดํ™”๋ฉด์„ ์ดˆ๊ณผํ•˜๋ฉด ์ „์ฒด ํ•œ์ค„ ๋ฐ€์–ด์˜ฌ๋ฆฌ๊ธฐ(scroll_screen())
25 * 80 = 2000; if text input exceeds the full screen, shift everything up by one line (scroll_screen()).

B.์ปค์„œ์œ„์น˜๋ฅผ ์—…๋ฐ์ดํŠธ / Update the cursor position

a)cursor % 80์€ x์ขŒํ‘œ๋กœ cursor๋ฅผ 80์œผ๋กœ ๋‚˜๋ˆˆ ๋‚˜๋จธ์ง€ ๊ฐ’์œผ๋กœ ์™ผ์ชฝ์œผ๋กœ๋ถ€ํ„ฐ ๋ช‡๋ฒˆ์งธ ์นธ์ธ์ง€๋ฅผ ๊ณ„์‚ฐํ•ฉ๋‹ˆ๋‹ค.
cursor % 80 calculates the x-coordinateโ€”specifically, the position from the leftโ€”by taking the remainder of the cursor value when divided by 80.

b)๋‚˜๋จธ์ง€๊ฐ€ 5๋ผ๋ฉด ์™ผ์ชฝ์œผ๋กœ ๋ถ€ํ„ฐ 5๋ฒˆ์งธ ์นธ์ด ๋ฉ๋‹ˆ๋‹ค.
If the remainder is 5, it corresponds to the 5th space from the left.

c)cursor / 80์€ y์ขŒํ‘œ๋กœ cursor๊ฐ€ 160์ธ ๊ฒฝ์šฐ 80์œผ๋กœ ๋‚˜๋ˆ„๋ฉด 2๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.
Dividing the y-coordinateโ€”in this case, 160โ€”by 80 results in 2.

d)๋ฐฐ์—ด์€ 0๋ฒˆ ๋ถ€ํ„ฐ ์‹œ์ž‘ํ•˜๋ฏ€๋กœ 3๋ฒˆ์งธ ์ค„์ด๋ฉ๋‹ˆ๋‹ค.
Since arrays start from index 0, this corresponds to the third row.

๐Ÿ“ ํ…Œ์ŠคํŠธ / Test

์Šคํฌ๋ฆฐ์ƒท / ScreenShot

๋งˆํƒœ๋ณต์Œ 21์žฅ 22์ ˆ / Matthew 21: 22

“๋„ˆํฌ๊ฐ€ ๊ธฐ๋„ํ•  ๋•Œ์— ๋ฌด์—‡์ด๋“ ์ง€ ๋ฏฟ๊ณ  ๊ตฌํ•˜๋Š” ๊ฒƒ์€ ๋‹ค ๋ฐ›์œผ๋ฆฌ๋ผ ํ•˜์‹œ๋‹ˆ๋ผ”

“And everything you ask in prayer, believing, you will receive.”

Leave a Reply