{"id":12594,"date":"2026-10-20T09:58:15","date_gmt":"2026-10-20T00:58:15","guid":{"rendered":"https:\/\/www.freelifemakers.org\/wordpress\/?p=12594"},"modified":"2026-10-21T18:07:32","modified_gmt":"2026-10-21T09:07:32","slug":"os-minios-text-2","status":"publish","type":"post","link":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/2026\/10\/20\/os-minios-text-2\/","title":{"rendered":"[OS]miniOS-Text-2"},"content":{"rendered":"\n<p>\ud83d\udc49\ud83c\udffb miniOS-Text-2\uc5d0\uc11c\ub294 \ud0a4\ubcf4\ub4dc\uc5d0 \ud0c0\uc774\ud551 \ud558\ub294 \uae00\uc790\ub97c \ud130\ubbf8\ub110\uc5d0 \ud45c\ud604\ud569\ub2c8\ub2e4.<br>In miniOS-Text-2, the characters typed on the keyboard are displayed in the terminal.<\/p>\n\n\n\n<p>\ud83d\udc49\ud83c\udffb \uae30\uc874\uc758 \uc5b4\uc148\ube14\ub7ec\ucf54\ub4dc\ub294 \ub3d9\uc77c\ud558\uace0 kernel.c\ucf54\ub4dc\ub9cc \uc218\uc815\ub418\uc5c8\uc2b5\ub2c8\ub2e4.<br>The existing assembler code remains the same; only the kernel.c code has been modified.<\/p>\n\n\n\n<p>\ud83d\udcc1 kernel.c<\/p>\n\n\n\n<p>\u2714\ufe0f \ub370\uc774\ud130 \ud0c0\uc785 \uc815\uc758 \/ Data Type Definition<\/p>\n\n\n\n<pre class=\"wp-block-code\" style=\"font-size:14px\"><code>typedef unsigned char byte;\ntypedef unsigned short word;<\/code><\/pre>\n\n\n\n<p>1)byte<br>-1 \ubc14\uc774\ud2b8 \ud06c\uae30\uc758 \ub370\uc774\ud130 \ud0c0\uc785(<code>unsigned char<\/code>)\uc73c\ub85c \uc815\uc758<br>Defined as a 1-byte-sized data type (unsigned char)<\/p>\n\n\n\n<p>-\ud558\ub4dc\uc6e8\uc5b4\uc5d0\uc11c \uc77d\uc5b4\uc624\ub294 \ub370\uc774\ud130\ub098 \ud3ec\ud2b8 \uc0c1\ud0dc\uac12\uc744 \ub2f4\uc744 \ub54c \uc0ac\uc6a9\ud568.<br>Used for storing data read from hardware or the status values \u200b\u200bof ports.<\/p>\n\n\n\n<p>2)word<br>-2\ubc14\uc774\ud2b8(16\ube44\ud2b8) \ud06c\uae30\uc758 \ub370\uc774\ud130 \ud0c0\uc785(<code>unsigned short<\/code>)\uc73c\ub85c \uc815\uc758<br>Defined as a 2-byte (16-bit) data type (unsigned short)<\/p>\n\n\n\n<p>-x86 \uc544\ud0a4\ud14d\ucc98\uc758 I\/O \ud3ec\ud2b8 \uc8fc\uc18c \ubc94\uc704(0 ~ 65535)\ub97c \uc548\uc804\ud558\uac8c \ub2f4\uae30 \uc704\ud574 \uc0ac\uc6a9\ud568.<br>Used to safely accommodate the I\/O port address range (0\u201365535) of the x86 architecture.<\/p>\n\n\n\n<p>\u2714\ufe0f I\/O \ud3ec\ud2b8\uc5d0\uc11c 1\ubc14\uc774\ud2b8\ub97c \uc77d\uc5b4\uc624\ub294 \ud568\uc218<br>Read 1 byte from I\/O port<\/p>\n\n\n\n<pre class=\"wp-block-code\" style=\"font-size:14px\"><code>static inline byte inb(word port) {\n    byte ret;\n    __asm__ __volatile__(\"inb %1, %0\" : \"=a\"(ret) : \"Nd\"(port));\n    return ret;\n}<\/code><\/pre>\n\n\n\n<p>1)\ud568\uc218\uc5d0 static \ud0a4\uc6cc\ub4dc\uac00 \ubd99\uc5b4 \uc788\uc73c\uba74 \uc774 \ud30c\uc77c \ub0b4\ubd80\uc6a9\uc73c\ub85c \uc0ac\uc6a9\ub418\ub294 \ud568\uc218\ub77c\ub294 \uc758\ubbf8\uc785\ub2c8\ub2e4. \uadf8\ub798\uc11c \ub2e4\ub978 \ud30c\uc77c\uc5d0\uc11c\ub294 static \ud0a4\uc6cc\ub4dc\uac00 \ubd99\uc740 \ud568\uc218\ub97c \uc0ac\uc6a9\ud560 \uc218 \uc5c6\uc74c.<br>When a function is marked with the <code>static<\/code> keyword, it means the function is intended for use only within that file. Consequently, such a function cannot be accessed from other files.<\/p>\n\n\n\n<p>\uc790\ubc14\ub098 \ucf54\ud2c0\ub9b0 \uac19\uc740 \uacbd\uc6b0 static\ud0a4\uc6cc\ub4dc\ub294 \ud074\ub798\uc2a4\uc640 \ub2ec\ub9ac \ucef4\ud30c\uc77c \uc2dc\uc810\uc5d0 \ud568\uc218\ub97c \uc2e4\ud589\uc2dc\ucf1c\uc11c \uba54\ubaa8\ub9ac\uc5d0 \uc62c\ub9ac\ub294 \ubc29\uc2dd\uc744 \uc758\ubbf8\ud568.<br>In languages \u200b\u200blike Java or Kotlin, the <code>static<\/code> keyword signifies that a function is executed and loaded into memory at compile time, rather than being associated with an instance of a class.<\/p>\n\n\n\n<p>\ud074\ub798\uc2a4\ub294 \uc778\uc2a4\ud134\uc2a4\uac00 \uc0dd\uc131\ub420\ub54c \uba54\ubaa8\ub9ac\uc5d0 \ud568\uc218\ub97c \uc2e4\ud589\ubc29\uc2dd.<br>A class functions by executing its methods in memory when an instance is created.<\/p>\n\n\n\n<p>\uac19\uc740 static \ud0a4\uc6cc\ub4dc\ub97c \uc0ac\uc6a9\ud574\ub3c4 c\uc5b8\uc5b4\uc758 static\uc758 \uac1c\ub150\uacfc \uc790\ubc14,\ucf54\ud2c0\ub9b0\uc5d0\uc11c\uc758 static\uc758 \uac1c\ub150\uc740 \ub2e4\ub984.<br>Although the same <code>static<\/code> keyword is used, the concept of <code>static<\/code> in C differs from its concept in Java or Kotlin.<\/p>\n\n\n\n<p>2)\ud568\uc218\uc5d0 <code>inline<\/code> \ud0a4\uc6cc\ub4dc\uac00 \ubd99\uc5b4 \uc788\uc73c\uba74, \ub2e4\ub978 \uacf3\uc5d0\uc11c \uc774 \ud568\uc218\ub97c \ud638\ucd9c\ud560 \ub54c \uc810\ud504(<code>call<\/code>)\ud558\uc9c0 \ub9d0\uace0, \uc774 \ud568\uc218\uc758 \ub0b4\ubd80 \ucf54\ub4dc\ub97c \ud638\ucd9c\ud55c \uadf8 \uc790\ub9ac\uc5d0 \uadf8\ub300\ub85c \ubcf5\uc0ac\ud574\uc11c \ubd99\uc5ec\ub123\uc73c\ub77c\ub294 \uc758\ubbf8\ub85c \uc131\ub2a5 \uc190\uc2e4\uc744 \uc5c6\uc560\ub294 \ucd5c\uc801\ud654 \uae30\ubc95\uc785\ub2c8\ub2e4.<br>When a function is marked with the <code>inline<\/code> keyword, it serves as an optimization technique that eliminates performance overhead: instead of performing a jump (a function call) when the function is invoked elsewhere, the code inside the function is copied and pasted directly into the location where it is called.<\/p>\n\n\n\n<pre class=\"wp-block-code\" style=\"font-size:14px\"><code>1.\uc77c\ubc18\uc810\ud504 \ubc29\uc2dd\uc758 \ucf54\ub4dc\n\/\/ \uba54\ubaa8\ub9ac \uc8fc\uc18c 0x1000 \ubc88\uc9c0 \/ memory address 0x1000\nvoid say_hello() {\n    print(\"\uc548\ub155\ud558\uc138\uc694\/Hello!\");\n}\n\n\/\/ \uba54\ubaa8\ub9ac \uc8fc\uc18c 0x2000 \ubc88\uc9c0 (main \ud568\uc218) \/ Memory address 0x2000 (main function)\nint main() {\n\/\/ \uc5ec\uae30\uc11c CPU\ub294 0x1000\ubc88\uc9c0\ub85c '\uc810\ud504(call)'\ud588\ub2e4\uac00 \ub3cc\uc544\uc635\ub2c8\ub2e4.\n\/\/ Here, the CPU 'jumps' (calls) to address 0x1000 and then returns.\n    say_hello(); \n    print(\"\ub05d\/End!\");\n}\n\n2.inline \ud568\uc218\/function\n\/\/ \ucef4\ud30c\uc77c\ub7ec\uac00 \uc9c1\uc811 say_hello() \ub0b4\ubd80\uc758 \uc54c\ub9f9\uc774\ub97c \ubcf5\uc0ac\ud574\uc11c main \ud568\uc218 \uc548\uc758 \uadf8 \uc790\ub9ac\uc5d0 \uadf8\ub300\ub85c \ub07c\uc6cc \ub123\uc2b5\ub2c8\ub2e4.\n\/\/ The compiler directly copies the contents of say_hello() and inserts them right into that spot within the main function.\n\n\/\/ \ucef4\ud30c\uc77c \ud6c4 \uc2e4\uc81c \uba54\ubaa8\ub9ac\uc5d0 \ub9cc\ub4e4\uc5b4\uc9c0\ub294 \ubaa8\uc591 (\uc810\ud504\uac00 \uc0ac\ub77c\uc9d0)\n\/\/ How it appears in actual memory after compilation (jumps are removed)\n\nint main() {\n\n\/\/ say_hello()\uc758 \ub0b4\uc6a9\uc774 \uadf8 \uc790\ub9ac\uc5d0 \ud1b5\uc9f8\ub85c \ubc15\ud798\n\/\/ The contents of say_hello() are inserted in their entirety at that spot.\n\n    print(\"\uc548\ub155\ud558\uc138\uc694\/Hello!\"); \n    print(\"\ub05d\/End!\");\n}<\/code><\/pre>\n\n\n\n<p>3)__asm__ \uc740 C\ucf54\ub4dc\uac00 \uc544\ub2cc \uc5b4\uc148\ube14\ub7ec\ub97c \uc2e4\ud589\ud55c\ub2e4\ub294 \uc758\ubbf8\ud568.<br><code>__asm__<\/code> indicates that the code following it is assembler, not C code.<\/p>\n\n\n\n<p>4)__volatile__\uc740 C\uc5b8\uc5b4\uc758 volatile \ud0a4\uc6cc\ub4dc\uc640 \uac19\uc740 \ub9e5\ub77d\uc73c\ub85c C\uc5b8\uc5b4\ub294 \ub611\uac19\uc740 \ucf54\ub4dc\uac00 \ubc18\ubcf5\ub418\uba74 \uc774\uc804 \uacb0\uacfc\uac12\uc744 \uc7ac\uc0ac\uc6a9\ud558\uac70\ub098 \ucf54\ub4dc \uc21c\uc11c\ub97c \ubc14\uafc0 \uc218 \uc788\uc74c.<br><code>__volatile__<\/code> follows the same logic as the <code>volatile<\/code> keyword in the C language; in C, when the same code is repeated, the compiler may reuse a previously calculated result or reorder the code.<\/p>\n\n\n\n<p>\ud558\ub4dc\uc6e8\uc5b4 \ud3ec\ud2b8(0x60 \ub4f1)\ub294 \uc6b0\ub9ac\uac00 \uc77d\uc744 \ub54c\ub9c8\ub2e4 \uc0c1\ud0dc\uac00 \uc2e4\uc2dc\uac04\uc73c\ub85c \ubcc0\ud560 \uc218 \uc788\uc5b4\uc11c \ucf54\ub4dc \uc7ac\uc0ac\uc6a9\uc774\ub098 \ucf54\ub4dc\uc21c\uc11c \ubc14\uafb8\uae30\ub97c \uae08\uc9c0\ud558\ub294 \ud0a4\uc6cc\ub4dc<br>Hardware ports (such as 0x60) are locations where the state can change in real time whenever they are read; therefore, a specific keyword is used to prohibit code reuse or the reordering of code operations.<\/p>\n\n\n\n<p>5)(&#8220;inb <em>%<\/em>1, <em>%<\/em>0&#8243; : &#8220;=a&#8221;(ret) : &#8220;Nd&#8221;(port))<\/p>\n\n\n\n<p>A.&#8221;inb %1, %0&#8243;<br><code>%1<\/code>\ubc88 \ud3ec\ud2b8\uc5d0\uc11c 1\ubc14\uc774\ud2b8\ub97c \uc77d\uc5b4\uc11c <code>%0<\/code>\uc5d0 \uc9d1\uc5b4\ub123\uae30 (<code>inb<\/code> = Input Byte).<br>Read 1 byte from port 1 and store it in %0<\/p>\n\n\n\n<p>B. : &#8220;=a&#8221;(ret)<br>\ucd9c\ub825\ubd80\ub85c inb \uba85\ub839\uc5b4\uac00 \ub05d\ub09c \ub4a4 \ud558\ub4dc\uc6e8\uc5b4 \uaddc\uce59\uc5d0 \ub530\ub77c AL(\ub610\ub294 EAX) \ub808\uc9c0\uc2a4\ud130\uc5d0 \ub2f4\uae34 \uacb0\uacfc\uac12\uc744 C\uc5b8\uc5b4 \ubcc0\uc218 ret\uc5d0 \uc9d1\uc5b4\ub123\uae30(=a\ub294 \ub808\uc9c0\uc2a4\ud130 \uc9c0\uc815 \ucf54\ub4dc)<br>After the <code>inb<\/code> instruction completes, the result\u2014stored in the AL (or EAX) register according to hardware conventions\u2014is assigned to the C variable <code>ret<\/code> (where <code>=a<\/code> is a code specifying the register to be used).<\/p>\n\n\n\n<p>C. : &#8220;Nd&#8221;(port)<br>\uc785\ub825\ubd80\ub85c C\uc5b8\uc5b4 \ubcc0\uc218 <code>port<\/code>\uc5d0 \ub4e4\uc5b4 \uc788\ub294 \ud3ec\ud2b8 \ubc88\ud638(\uc608: <code>0x60<\/code>)\ub97c \uc5b4\uc148\ube14\ub9ac \uba85\ub839\uc5b4\uac00 \uc4f8 \uc218 \uc788\ub3c4\ub85d \uc801\uc808\ud55c \ub808\uc9c0\uc2a4\ud130\ub098 \uc0c1\uc218\ub85c \uc804\ub2ec\ud558\uae30<br>Pass the port number (e.g., 0x60) contained in the C variable <code>port<\/code> to an appropriate register or constant so that it can be used by assembly instructions.<\/p>\n\n\n\n<p>D. \uacb0\uad6d \uc704\uc758 \ucf54\ub4dc\ub294 \uc5b4\uc148\ube14\ub7ec inb\uba85\ub839\uc5b4\ub85c port\uc5d0\uc11c \uac12\uc744 \uc77d\uc5b4\uc640\uc11c ret\ubcc0\uc218\uc5d0 \uc800\uc7a5\ud558\ub294 \uc5ed\ud560\uc744 \ud568.<br>Ultimately, the code above performs the task of reading a value from a port using the assembler <code>inb<\/code> instruction and storing it in the <code>ret<\/code> variable.<\/p>\n\n\n\n<p>E.%0,%1\uc740 \uc21c\uc11c\ub300\ub85c 0\ubc88\ubd80\ud130 \ubc88\ud638\ub97c \ub9e4\uae30\uae30 \uc2dc\uc791\ud568.<br>%0 and %1 are numbered sequentially, starting from 0.<\/p>\n\n\n\n<p>\u2714\ufe0f \ud0a4\ubcf4\ub4dc\uc5d0\uc11c \uc785\ub825\ubc1b\uc740 \uc2a4\uce94\ucf54\ub4dc\ub97c \uae30\ubcf8 ASCII \ubb38\uc790\ub85c \ubcc0\ud658\ud558\uae30<br>Converting scan codes received from the keyboard into standard ASCII characters<\/p>\n\n\n\n<pre class=\"wp-block-code\" style=\"font-size:14px\"><code>char scancode_to_ascii(byte scancode) {\n    \/\/ \ud0a4\ubcf4\ub4dc Set 1 \uc8fc\uc694 \ud0a4 \ub9e4\ud551 (\uc601\ubb38 \uc18c\ubb38\uc790, \uc22b\uc790, \uc77c\ubd80 \ud2b9\uc218\ubb38\uc790)\n    \/\/ Key mappings for Keyboard Set 1 (lowercase English letters, numbers, and select special characters)\n    char table&#91;128] = {\n        0,  27, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', '\\b',\n        '\\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '&#91;', ']', '\\n',\n        0, 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\\'', '`',\n        0, '\\\\', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '\/', 0,\n        '*', 0, ' '\n    };\n    \n    if (scancode &lt; 128) {\n        return table&#91;scancode];\n    }\n    return 0;\n}<\/code><\/pre>\n\n\n\n<p>1)\ud0a4\ubcf4\ub4dc\uc5d0\uc11c a\ub97c \ub204\ub978\uacbd\uc6b0<br>If you press &#8216;a&#8217; on the keyboard<\/p>\n\n\n\n<p>A.\ud0a4\ubcf4\ub4dc &#8216;a&#8217;\ub294 <code>0x1E<\/code>(\uc2ed\uc9c4\uc218\ub85c 30)\uc785\ub2c8\ub2e4.<br>The keyboard key &#8216;a&#8217; is 0x1E (30 in decimal).<\/p>\n\n\n\n<p>B.&#8217;a&#8217;\ub294 \ubc30\uc5f4 30\ubc88\uc5d0 \uc788\uc2b5\ub2c8\ub2e4.<br>&#8216;a&#8217; is at index 30 of the array.<\/p>\n\n\n\n<p>C.ASCII\ubb38\uc790\ub77c\uace0 \ud558\ub294 \uaddc\uce59\uc5d0 \uc758\ud558\uba74 30\ubc88\uc740 &#8216;a&#8217;\ub77c\ub294 \ubb38\uc790\uc785\ub2c8\ub2e4.<br>According to the rules known as ASCII, the number 30 corresponds to the character &#8216;a&#8217;.<\/p>\n\n\n\n<p>D.\uadf8\ub798\uc11c \ubc30\uc5f4 30\ubc88\uc5d0\uc11c \ubb38\uc790\ub97c \ucc3e\uc73c\uba74 &#8216;a&#8217;\ub77c\ub294 \ubb38\uc790\ub97c \ucc3e\uc744 \uc218 \uc788\uace0 \uc774 \uac12\uc744 \ub9ac\ud134\ud574 \uc90d\ub2c8\ub2e4.<br>So, if you look for a character at index 30 of the array, you will find the character &#8216;a&#8217;, and this value is then returned.<\/p>\n\n\n\n<p>2)\\b\ub294 \ubc31\uc2a4\ud398\uc774\uc2a4(Backspace), \\t\ub294 \ud0ed(Tab), \\n\uc740 \uc5d4\ud130(Enter) \ud0a4\ub97c \uc758\ubbf8\ud569\ub2c8\ub2e4.<br>\\b represents the Backspace key, \\t represents the Tab key, and \\n represents the Enter key.<\/p>\n\n\n\n<p>3)\uc911\uac04\uc5d0 0\uc774 \ub4e4\uc5b4 \uc788\ub294 \ubd80\ubd84\uc740 \ubb38\uc790\ub85c \ucd9c\ub825\ub418\uc9c0 \uc54a\ub294 \ud2b9\uc218 \ud0a4(\uc608: Shift, Ctrl, F\ud0a4 \ub4f1)\uc774\uac70\ub098 \uc544\uc9c1 \ub9e4\ud551\ub418\uc9c0 \uc54a\uc740 \ucf54\ub4dc\uc5ec\uc11c \ubb34\uc2dc\ud558\ub3c4\ub85d \ucc98\ub9ac\ud55c \uac83\uc785\ub2c8\ub2e4.<br>Entries containing a 0 have been ignored because they either represent special keys that do not produce printable characters (such as Shift, Ctrl, or F-keys) or correspond to codes that have not yet been mapped.<\/p>\n\n\n\n<p>4)\ud0a4\ubcf4\ub4dc\uc5d0\uc11c \ud0a4\ub97c \ub204\ub97c \ub54c \ubc1c\uc0dd\ud558\ub294 \uc2a4\uce94\ucf54\ub4dc\ub294 0\ubd80\ud130 127 \uc0ac\uc774\uc758 \uac12\uc785\ub2c8\ub2e4. (\ud0a4\ub97c \ub5c4 \ub54c\ub294 \uc774\ubcf4\ub2e4 128\uc774 \ub354 \ud070 \uac12\uc774 \ub4e4\uc5b4\uc635\ub2c8\ub2e4.)<br>The scan code generated when a key is pressed on a keyboard is a value between 0 and 127. (When the key is released, a value 128 greater than this is received.)<\/p>\n\n\n\n<p>5)\uc785\ub825\ubc1b\uc740 \uc2a4\uce94\ucf54\ub4dc\uac00 128\ubcf4\ub2e4 \uc791\ub2e4\uba74, \ubc30\uc5f4\uc5d0\uc11c \uace7\ubc14\ub85c \ubb38\uc790\ub97c \ucc3e\uc544 \ubc18\ud658(table[scancode])\ud569\ub2c8\ub2e4.<br>If the input scancode is less than 128, the corresponding character is retrieved directly from the array and returned (table[scancode]).<\/p>\n\n\n\n<p>6)\ubc94\uc704\ub97c \ubc97\uc5b4\ub098\uac70\ub098 \uc798\ubabb\ub41c \uac12\uc774\uba74 0(Null)\uc744 \ubc18\ud658\ud558\uc5ec \ubb38\uc790\ub85c \ucc98\ub9ac\ud558\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4.<br>If a value is out of range or incorrect, it returns 0 (Null) and is not treated as a character.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p>\u2714\ufe0f \ud0a4\ubcf4\ub4dc \uc785\ub825 \uac10\uc9c0 \/ Detect keyboard input<\/p>\n\n\n\n<pre class=\"wp-block-code\" style=\"font-size:14px\"><code>while (1) {\n    byte status = inb(0x64);\n... ...\n}<\/code><\/pre>\n\n\n\n<p>1)\ubb34\ud55c\ub8e8\ud504\ub85c \ud0a4\ubcf4\ub4dc \uc785\ub825(0x64\ubc88 \ud3ec\ud2b8)\uc744 \uac10\uc9c0<br>Detect keyboard input (port 0x64) in an infinite loop<\/p>\n\n\n\n<p>2)0x64\ubc88 \ud3ec\ud2b8\uc758 \uac12(status)\uc744 1\ubc14\uc774\ud2b8 \uc77d\uc5b4\uc640\uc11c status\ubcc0\uc218\uc5d0 \uc800\uc7a5<br>Read a 1-byte value (status) from port 0x64 and store it in the variable &#8216;status&#8217;.<\/p>\n\n\n\n<p>\u2714\ufe0f \uc77d\uc744 \ub370\uc774\ud130\uac00 \uc788\ub294\uc9c0 \ud655\uc778\ud558\uae30<br>Check if there is data to read<\/p>\n\n\n\n<p>1)0x64\ubc88 \ud0a4\ubcf4\ub4dc \uc0c1\ud0dc \ud3ec\ud2b8\uc5d0\uc11c \uc77d\uc5b4\uc628 \uac12\uc758 \uac00\uc7a5 \uc6b0\uce21 \uac12\uc774 1\ubc88\uc778\uc9c0 \ud655\uc778<br>Check whether the rightmost bit of the value read from the keyboard status port (0x64) is 1.<\/p>\n\n\n\n<pre class=\"wp-block-code\" style=\"font-size:14px\"><code> if (status &amp; 0x01) { ... }<\/code><\/pre>\n\n\n\n<p>1)&amp;\uc740 \ube44\ud2b8 \uc5f0\uc0b0\uc790 &amp;&amp;\ub294 \ub17c\ub9ac\uc5f0\uc0b0\uc790<br>&amp; is a bitwise operator, while &amp;&amp; is a logical operator.<\/p>\n\n\n\n<p>2)<code>status<\/code>\uc758 \uac12\uc774 <code>0x25<\/code> (\uc774\uc9c4\uc218\ub85c <code>0010 0101<\/code>)\uc778\uacbd\uc6b0 \ube44\ud2b8 \uc5f0\uc0b0\ud558\uba74 1\uc774\ub428(AND\uc5f0\uc0b0\uc774\ubbc0\ub85c \ub450 \uac12\ubaa8\ub450 1\uc778 \uacbd\uc6b0\ub9cc 1\uc774\ub428.)<br>If the value of <code>status<\/code> is 0x25 (0010 0101 in binary), performing a bitwise operation results in 1 (since it is an AND operation, the result is 1 only if both values \u200b\u200bare 1).<\/p>\n\n\n\n<pre class=\"wp-block-code\" style=\"font-size:14px\"><code>0010 0101 &amp; 0000 0001 = 0000 0001<\/code><\/pre>\n\n\n\n<p>4)\uac00\uc7a5 \uc6b0\uce21 \uac12\uc774 1\uc778\uac74 \ucd9c\ub825 \ubc84\ud37c\uac00 \uaf49 \ucc3c\ub294\uc9c0 \uc54c\ub824\uc8fc\ub294 OBF \ube44\ud2b8\ub97c \ud655\uc778\ud558\ub294 \ucf54\ub4dc<br>The value 1 in the rightmost position is for checking the OBF bit, which indicates whether the output buffer is full.<\/p>\n\n\n\n<p>5)\uc989 CPU\uc5d0\uc11c \uac00\uc838\uac08 \ub370\uc774\ud130\uac00 \uc788\ub2e4\ub294 \uc758\ubbf8<br>In other words, it means there is data for the CPU to retrieve.<\/p>\n\n\n\n<p>6)\ud0a4\ubcf4\ub4dc\ub85c \ud0c0\uc774\ud551\ud558\ub294 \uc21c\uac04 \ucd9c\ub825\ubc84\ud37c\uc5d0 \uc2a4\uce94\ucf54\ub4dc\uac00 \ucc44\uc6cc\uc9d0.<br>The moment you type on the keyboard, the output buffer is filled with scan codes.<\/p>\n\n\n\n<p>\u2714\ufe0f \ub370\uc774\ud130 \uc77d\uc5b4\uc624\uae30 \/ Reading data<\/p>\n\n\n\n<pre class=\"wp-block-code\" style=\"font-size:14px\"><code>byte scancode = inb(0x60); <\/code><\/pre>\n\n\n\n<p>1)\ub370\uc774\ud130 \ud3ec\ud2b8(0x60)\uc5d0\uc11c \uc2a4\uce94\ucf54\ub4dc\ub97c \uc77d\uc5b4\uc624\uae30<br>Read a scan code from the data port (0x60)<\/p>\n\n\n\n<p>2)\uc774\ub54c \ucd9c\ub825\ubc84\ud37c\uac00 \ube44\uc6cc\uc9c0\uace0 \uc0c1\ud0dc \ud3ec\ud2b8(<code>0x64<\/code>)\uc758 OBF(Output Buffer Full) \ube44\ud2b8\ub3c4 \ub2e4\uc2dc <code>0<\/code>\uc774\ub428.<br>At this point, the output buffer is cleared, and the OBF (Output Buffer Full) bit in the status port (0x64) is also reset to 0.<\/p>\n\n\n\n<p>\u2714\ufe0f \ud654\uba74\uc5d0 \uae00\uc790 \ucd9c\ub825 \/ Display text on the screen<\/p>\n\n\n\n<pre class=\"wp-block-code\" style=\"font-size:14px\"><code>            if (!(scancode &amp; 0x80)) {\n                char c = scancode_to_ascii(scancode);\n                if (c != 0) {\n                    \/\/ \ud654\uba74\uc5d0 \uae00\uc790 \ucd9c\ub825 \/ Display text on the screen\n                    vram&#91;cursor * 2]     = c;\n                    vram&#91;cursor * 2 + 1] = 0x0F; \/\/ \ud770\uc0c9 \uae00\uc790 \/ White text\n                    cursor++;\n                }\n            }<\/code><\/pre>\n\n\n\n<p>1)!(scancode &amp; 0x80)<br>\uc9c0\uae08 \ub4e4\uc5b4\uc628 \uc2a4\uce94\ucf54\ub4dc\uac00 \uc190\uc744 \ub5bc\uc11c \ubc1c\uc0dd\ud55c \uc2e0\ud638\uac00 \uc544\ub2c8\ub77c\uba74(\uc989, \ub204\ub978 \uc2e0\ud638\uac00 \ub9de\ub2e4\uba74) \ub2e4\uc74c \ub85c\uc9c1\uc744 \uc2e4\ud589<br>If the scan code received is not a signal generated by releasing the hand (i.e., if it is a pressed signal), execute the next logic.<\/p>\n\n\n\n<p>\ud0a4\ub97c \ub204\ub97c\ub54c\uc640 \uc190\uc744\ub5c4\ub5bc \ub2e4\ub978 \uc2a4\uce94\ucf54\ub4dc\ub97c \ubcf4\ub0c4<br>Different scan codes are sent when a key is pressed and when it is released.<\/p>\n\n\n\n<p><code>0x80<\/code>\uc740 \uc774\uc9c4\uc218\ub85c <code>1000 0000<\/code> \ucd5c\uc0c1\uc704\ube44\ud2b8(\uac00\uc7a5 \uc88c\uce21 \uac12)\ub9cc 1 \ub098\uba38\uc9c0\ub294 \ubaa8\ub450 0<br>0x80 is 1000 0000 in binary, where only the most significant bit (the leftmost bit) is 1, and all other bits are 0.<\/p>\n\n\n\n<p>\uc544\ub798\ub294 &#8216;a'(0x1E)\ud0a4\ub97c \ub204\ub97c \ub54c\uc758 \uacfc\uc815<br>Below is the process when pressing the &#8216;a&#8217; (0x1E) key<\/p>\n\n\n\n<p>A.\ud0a4\ub97c \ub204\ub97c \ub54c  \/ When pressing a key<\/p>\n\n\n\n<pre class=\"wp-block-code\" style=\"font-size:14px\"><code>0001 1110  (0x1E, a \ud0a4 \ub204\ub97c \ub54c \uc2a4\uce94\ucf54\ub4dc \/ Scan code when the 'a' key is pressed)\n&amp; 1000 0000  (0x80, \ud544\ud130 \/ filter)\n------------\n  0000 0000  (\uacb0\uacfc \/ result: 0)<\/code><\/pre>\n\n\n\n<p>a)(scancode &amp; 0x80) \uc774 \uac12\uc774 0\uc989 false\uac00 \ub428.<br>The value of (scancode &amp; 0x80) becomes 0, which is false.<\/p>\n\n\n\n<p>b)\uc2e4\uc81c\ucf54\ub4dc\uc5d0\uc11c\ub294 !(scancode &amp; 0x80) \uc774\ubbc0\ub85c true\uac00 \ub428.<br>In the actual code, it evaluates to true because of !(scancode &amp; 0x80).<\/p>\n\n\n\n<p>B.\ud0a4\uc5d0\uc11c \uc190\uc744 \ub5fc \ub584<br>When you take your hand off the key<\/p>\n\n\n\n<pre class=\"wp-block-code\" style=\"font-size:14px\"><code>1001 1110  (0x9E, a \ud0a4 \ub5c4 \ub54c \uc2a4\uce94\ucf54\ub4dc \/ Scan code when the 'a' key is released)\n&amp; 1000 0000  (0x80, \ud544\ud130 \/ filter)\n------------\n  1000 0000  (\uacb0\uacfc\/result : 0x80, \uc989 0\uc774 \uc544\ub2cc \uac12 \/ In other words, a non-zero value)<\/code><\/pre>\n\n\n\n<p>a) \uacb0\uacfc\uac00 0\uc774 \uc544\ub2cc\uac12\uc740 \ubaa8\ub450 true\uac00 \ub428.<br>Any result with a non-zero value is considered true.<\/p>\n\n\n\n<p>b)\uc2e4\uc81c\ucf54\ub4dc\uc5d0\uc11c\ub294 !(scancode &amp; 0x80) \uc774\ubbc0\ub85c false\uac00 \ub428.<br>In the actual code, <code>!(scancode &amp; 0x80)<\/code> evaluates to <code>false<\/code>.<\/p>\n\n\n\n<p>2)\ud0a4\ubcf4\ub4dc \uc785\ub825\uac12\uacfc \ud544\ud130\uac12(0x80,)\uc744 AND\uc5f0\uc0b0 \uacb0\uacfc \uac12\uc73c\ub85c true,false\ub97c \uacb0\uc815<br>Determine true or false based on the result of an AND operation between the keyboard input value and the filter value (0x80).<\/p>\n\n\n\n<p>3)\uc704\uc758 \uacb0\uacfc \uac12\uc73c\ub85c \ud0a4\ubcf4\ub4dc\ub97c \ub204\ub978\uacbd\uc6b0 \ucf54\ub4dc \uc2e4\ud589,\uc190\uc744 \ub5bc\uba74 \ucf54\ub4dc\ub97c \uc2e4\ud589\ud558\uc9c0 \uc54a\uc74c<br>Based on the results above, the code executes when a key is pressed, and does not execute when the key is released.<\/p>\n\n\n\n<p>4)\ud0a4\ubcf4\ub4dc\uc758 \ud0a4\ub97c \ub204\ub978\uacbd\uc6b0 \ud654\uba74\uc5d0 \ubb38\uc790 \ucd9c\ub825<br>Characters are displayed on the screen when a keyboard key is pressed.<\/p>\n\n\n\n<pre class=\"wp-block-code\" style=\"font-size:14px\"><code>                char c = scancode_to_ascii(scancode);\n                if (c != 0) {\n                    \/\/ \ud654\uba74\uc5d0 \uae00\uc790 \ucd9c\ub825 \/ Display text on the screen\n                    vram&#91;cursor * 2]     = c;\n                    vram&#91;cursor * 2 + 1] = 0x0F; \/\/ \ud770\uc0c9 \uae00\uc790 \/ White text\n                    cursor++;\n                }<\/code><\/pre>\n\n\n\n<p>A. \uc9dd\uc218\ubc30\uc5f4\uc5d0 \ubb38\uc790\uc758 ASCII \ucf54\ub4dc \uac12 \uc785\ub825<br>Store the ASCII code values \u200b\u200bof characters in the even-indexed positions of the array.<\/p>\n\n\n\n<p>B.\ud640\uc218\ubc30\uc5f4\uc5d0\ub294 \uae00\uc790\uc758 \uc0c9\uc0c1 \ubc0f  \uc18d\uc131 \uc815\ubcf4\uac00 \uc785\ub825\ub428<br>The odd-indexed arrays contain information regarding character color and attributes.<\/p>\n\n\n\n<p>C.0x0F\ub294 \ubc14\uc774\ud2b8\ub97c \ubc18\uc73c\ub85c \ub098\ub204\uc5b4 \uc0c9\uc0c1\uc744 \ud45c\ud604<br>0x0F divides the byte in half to represent the color.<\/p>\n\n\n\n<p>\uc55e\uc758 <code>0<\/code>\uc740 \ubc30\uacbd\uc0c9 (\uac80\uc740\uc0c9),\ub4a4\uc758 F\ub294 \uae00\uc790\uc0c9 (\ubc1d\uc740 \ud770\uc0c9)<br>The &#8216;0&#8217; at the beginning represents the background color (black), and the &#8216;F&#8217; at the end represents the text color (bright white).<\/p>\n\n\n\n<p>\u2714\ufe0f \ucef4\ud30c\uc77c \/ Compile<\/p>\n\n\n\n<p>&#8212; \uc258\uc2a4\ud06c\ub9bd\ud2b8\ub85c build.sh\ud30c\uc77c\uc744 \ub9cc\ub4e4\uc5b4\uc11c \ucef4\ud30c\uc77c\ud558\uba74 \ub9e4\uc6b0 \ud3b8\ud569\ub2c8\ub2e4.<br>Creating a <code>build.sh<\/code> shell script to handle compilation makes things very convenient.<\/p>\n\n\n\n<p>1)build.sh<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#!\/bin\/bash\n\n# 1. \uae30\uc874 \ube4c\ub4dc \ud30c\uc77c \ubc0f \uc774\ubbf8\uc9c0 \uc815\ub9ac\n# Clean up existing build files and images\necho \"&#91;*] Cleaning old build files...\"\nrm -f *.bin *.o *.img temp.bin sector2.bin\n\n# 2. \ubd80\ud2b8\ub85c\ub354 \ucef4\ud30c\uc77c\n# Bootloader compilation\necho \"&#91;*] Compiling boot.asm...\"\nnasm -f bin boot.asm -o boot.bin\n\n# 3. \uc5b4\uc148\ube14\ub9ac \uc2a4\ud141 \ucef4\ud30c\uc77c (ELF32)\n# Assembly Stub Compilation (ELF32)\necho \"&#91;*] Compiling sector2.asm...\"\nnasm -f elf32 sector2.asm -o sector2.o\n\n# 4. C \ucee4\ub110 \ucef4\ud30c\uc77c\n# C Kernel Compilation\necho \"&#91;*] Compiling kernel.c...\"\ni686-elf-gcc -m32 -c kernel.c -o kernel.o -nostdlib -fno-builtin -fno-stack-protector -fno-pic -fno-PIE\n\n# 5. \ub9c1\ucee4 \uc2e4\ud589\n# Run linker\necho \"&#91;*] Linking objects...\"\ni686-elf-ld -m elf_i386 -Ttext 0x8000 -e start -o sector2.bin sector2.o kernel.o --oformat binary\n\n# 6. \ubc14\uc774\ub108\ub9ac \ubcd1\ud569 \ubc0f \ub514\uc2a4\ud06c \uc774\ubbf8\uc9c0 \uc0dd\uc131\n# Binary Merging and Disk Image Creation\necho \"&#91;*] Creating floppy disk image...\"\ncat boot.bin sector2.bin &gt; temp.bin\ndd if=temp.bin of=os.img bs=512 count=2880 conv=sync\n\n# 7. QEMU \uc2e4\ud589\n# Running QEMU\necho \"&#91;*] Running QEMU...\"\nqemu-system-x86_64 -drive file=os.img,format=raw,if=floppy -boot a -display cocoa<\/code><\/pre>\n\n\n\n<p>2)\uc258\uc2a4\ud06c\ub9bd\ud2b8 \uc2e4\ud589<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>chmod +x build.sh\n.\/build.sh<\/code><\/pre>\n\n\n\n<p>\ud83d\udcc1 \ud14c\uc2a4\ud2b8 \/ Test<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"700\" height=\"481\" src=\"https:\/\/www.freelifemakers.org\/wordpress\/wp-content\/uploads\/2026\/10\/miniOS-Text-2-jpg.jpg\" alt=\"\" class=\"wp-image-12650\" srcset=\"https:\/\/www.freelifemakers.org\/wordpress\/wp-content\/uploads\/2026\/10\/miniOS-Text-2-jpg.jpg 700w, https:\/\/www.freelifemakers.org\/wordpress\/wp-content\/uploads\/2026\/10\/miniOS-Text-2-jpg-300x206.jpg 300w, https:\/\/www.freelifemakers.org\/wordpress\/wp-content\/uploads\/2026\/10\/miniOS-Text-2-jpg-400x275.jpg 400w\" sizes=\"auto, (max-width: 700px) 100vw, 700px\" \/><figcaption class=\"wp-element-caption\">ScreenShot<\/figcaption><\/figure>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>\ub9c8\ud0dc\ubcf5\uc74c 21\uc7a5 22\uc808 \/ Matthew 21: 22<\/p>\n\n\n\n<p>&#8220;\ub108\ud76c\uac00 \uae30\ub3c4\ud560 \ub54c\uc5d0 \ubb34\uc5c7\uc774\ub4e0\uc9c0 \ubbff\uace0 \uad6c\ud558\ub294 \uac83\uc740 \ub2e4 \ubc1b\uc73c\ub9ac\ub77c \ud558\uc2dc\ub2c8\ub77c&#8221;<\/p>\n\n\n\n<p>&#8220;And everything you ask in prayer, believing, you will receive.&#8221;<\/p>\n<\/blockquote>\n","protected":false},"excerpt":{"rendered":"<p>\ud83d\udc49\ud83c\udffb miniOS-Text-2\uc5d0\uc11c\ub294 \ud0a4\ubcf4\ub4dc\uc5d0 \ud0c0\uc774\ud551 \ud558\ub294 \uae00\uc790\ub97c \ud130\ubbf8\ub110\uc5d0 \ud45c\ud604\ud569\ub2c8\ub2e4.In miniOS-Text-2, the characters typed on the keyboard are displayed in the terminal. \ud83d\udc49\ud83c\udffb \uae30\uc874\uc758 \uc5b4\uc148\ube14\ub7ec\ucf54\ub4dc\ub294 \ub3d9\uc77c\ud558\uace0 kernel.c\ucf54\ub4dc\ub9cc \uc218\uc815\ub418\uc5c8\uc2b5\ub2c8\ub2e4.The existing assembler code remains the same; only the kernel.c code has been modified. \ud83d\udcc1 kernel.c \u2714\ufe0f \ub370\uc774\ud130 \ud0c0\uc785 \uc815\uc758 \/ Data Type Definition 1)byte-1 \ubc14\uc774\ud2b8 \ud06c\uae30\uc758 \ub370\uc774\ud130 \ud0c0\uc785(unsigned char)\uc73c\ub85c [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[28,26,1],"tags":[],"class_list":["post-12594","post","type-post","status-publish","format-standard","hentry","category-news","category-os","category-uncategorized","missing-thumbnail"],"_links":{"self":[{"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/posts\/12594","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/comments?post=12594"}],"version-history":[{"count":66,"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/posts\/12594\/revisions"}],"predecessor-version":[{"id":12663,"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/posts\/12594\/revisions\/12663"}],"wp:attachment":[{"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/media?parent=12594"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/categories?post=12594"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/tags?post=12594"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}