๐๐ป 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.”