1 00:00:00,500 --> 00:00:04,019 Hello, in this lecture we will start building our kernel. 2 00:00:04,820 --> 00:00:10,970 The first thing we will do in the kernel is manage the system resources in one place such as 3 00:00:10,970 --> 00:00:12,140 gdt and idt. 4 00:00:14,350 --> 00:00:16,960 So we copy and paste the gdt here. 5 00:00:23,740 --> 00:00:29,560 Alright, we write load gdt and gdt pointer. 6 00:00:33,780 --> 00:00:37,710 Notice that the address of gdt in gdt pointer is 8 bytes. 7 00:00:38,660 --> 00:00:42,630 or quadword. In 64-bit mode, 8 00:00:42,650 --> 00:00:47,070 we load the pointer with 2-byte limit and 8-byte base address. 9 00:00:48,910 --> 00:00:52,330 So we need to change the double word to quadword. 10 00:00:53,240 --> 00:01:00,350 What we are going to do next is we are going to load the code segment descriptor into cs register. 11 00:01:00,350 --> 00:01:01,890 Instead of using jump instruction, 12 00:01:02,170 --> 00:01:06,590 we load the descriptor using another instruction return instruction. 13 00:01:07,220 --> 00:01:09,830 So we write retf 14 00:01:10,740 --> 00:01:18,690 indicating that this is a far return. Normal return will not load the descriptor in cs register. 15 00:01:18,690 --> 00:01:23,550 So we use far return to do that. In most cases, when we execute return instruction, 16 00:01:23,970 --> 00:01:27,420 we know that we will return from current procedure to the caller. 17 00:01:28,590 --> 00:01:34,890 The return address is pushed on the stack by the caller and go to the procedure. 18 00:01:34,890 --> 00:01:39,980 In the procedure, return instruction will pop the address in rip register which will branch to that location. 19 00:01:40,500 --> 00:01:43,650 Apparently, what we are doing here is not the case. 20 00:01:44,960 --> 00:01:51,470 What we are actually doing here is fabricate the scenario where we are called by other caller 21 00:01:51,500 --> 00:01:55,340 and the far return instruction executes and we are back to the caller. 22 00:01:56,470 --> 00:02:02,110 So the return address need to be pushed on the stack on our own and we will jump to that address 23 00:02:02,200 --> 00:02:03,520 when far return executes. 24 00:02:05,140 --> 00:02:11,050 Generally we have two situations regarding to far return. One is return to the same privilege level 25 00:02:11,050 --> 00:02:13,280 which is what we are doing right now. 26 00:02:13,780 --> 00:02:16,680 Another is return to the different privilege level. 27 00:02:17,310 --> 00:02:21,210 When we jump to ring 3, we will use this technique. 28 00:02:21,220 --> 00:02:23,440 For the moment, let’s see how to do the same privilege level far return. 29 00:02:23,440 --> 00:02:27,710 As you see, the top of stack should be like this. 30 00:02:28,300 --> 00:02:35,650 The first 8 bytes are the code segment selector, here we choose 8. Because the code segment descriptor is 31 00:02:35,650 --> 00:02:37,540 the second entry of gdt. 32 00:02:39,080 --> 00:02:40,480 So we push 8. 33 00:02:42,380 --> 00:02:48,610 Then the offset is in the next 8 bytes. So we save the address of location we want to branch in here 34 00:02:48,680 --> 00:02:52,820 and we define the label kernel entry 35 00:02:55,030 --> 00:02:56,620 to represent this location. 36 00:02:59,280 --> 00:03:00,210 Let's define it. 37 00:03:03,390 --> 00:03:10,850 Ok push these two data on the stack and then we can execute return instruction. Also, note that the default operand size 38 00:03:10,870 --> 00:03:14,400 of far return is 32 bits. 39 00:03:14,400 --> 00:03:17,000 Each data we pushed on the stack is 64 bits. 40 00:03:17,460 --> 00:03:20,610 So we need to add operand-size override prefix 41 00:03:22,290 --> 00:03:26,250 48 ourselves to change the operand size to 64-bits. 42 00:03:30,880 --> 00:03:36,130 In the kernel entry, we simply print K and add the infinite loop in the end. 43 00:03:37,030 --> 00:03:38,320 So we move the code 44 00:03:40,000 --> 00:03:41,040 to kernel entry. 45 00:03:45,540 --> 00:03:48,210 Alright, let’s build the project and see the result. 46 00:03:59,110 --> 00:04:01,480 As you can see, the character K is printed.