1 00:00:00,900 --> 00:00:01,800 Hello, everyone. 2 00:00:02,220 --> 00:00:07,950 in this lecture we will write our own library functions used in the kernel, such as memory copy, 3 00:00:07,950 --> 00:00:09,540 memory set, etc. 4 00:00:10,620 --> 00:00:12,120 The file is called lib. 5 00:00:13,150 --> 00:00:14,110 We create 6 00:00:15,460 --> 00:00:16,180 a new file 7 00:00:19,100 --> 00:00:20,300 call lib.h 8 00:00:24,510 --> 00:00:27,480 Just like we did before, we create a guard. 9 00:00:33,880 --> 00:00:37,240 So if this label is not defined, we define it. 10 00:00:42,490 --> 00:00:48,130 The first function is memory set which is pretty much the same as the one in c standard library. 11 00:00:52,730 --> 00:00:59,030 In our memory set function, we return no value and the first parameter is the address of the memory being set. 12 00:01:03,080 --> 00:01:06,530 The second parameter is the value we want to set the memory with. 13 00:01:10,550 --> 00:01:14,780 The size of the memory we want to set is specified in the last parameter. 14 00:01:18,100 --> 00:01:22,870 OK, the next two functions are related to the memory copy. 15 00:01:25,150 --> 00:01:27,220 The memory move 16 00:01:31,630 --> 00:01:32,830 and memory copy 17 00:01:33,870 --> 00:01:34,340 . 18 00:01:36,630 --> 00:01:38,760 They are the same function in our system. 19 00:01:40,190 --> 00:01:43,000 The first parameter of the function is destination 20 00:01:47,030 --> 00:01:49,520 and the source is stored in the second parameter. 21 00:01:52,180 --> 00:01:55,390 The last parameter stores the size of bytes need copying. 22 00:02:01,380 --> 00:02:05,130 The last function is memory compare. Unlike the above functions, 23 00:02:07,720 --> 00:02:14,860 it returns an integer. Here if the return value is 0, it means the result of comparison is equal. 24 00:02:14,860 --> 00:02:15,660 Otherwise they are not equal. 25 00:02:16,860 --> 00:02:21,350 The first two parameters are the addresses of two memory areas being compared. 26 00:02:27,940 --> 00:02:30,400 The size is specified in the last parameter. 27 00:02:33,420 --> 00:02:39,090 Ok, for now we only implement these four functions. We will add more functions as we move on. 28 00:02:40,510 --> 00:02:46,540 And also these functions are implemented using assembly language, since we have the corresponding instructions 29 00:02:46,540 --> 00:02:47,780 to perform the tasks. 30 00:02:48,460 --> 00:02:50,290 So we create assembly file. 31 00:02:54,760 --> 00:02:57,010 We call it lib.asm 32 00:03:01,040 --> 00:03:02,120 In the text section, 33 00:03:05,460 --> 00:03:09,360 we declare the functions globally so that we can use them in the C files. 34 00:03:19,050 --> 00:03:26,370 Ok now we write memory set function. So we define label memset. We use instruction cld 35 00:03:26,380 --> 00:03:33,870 which clears the direction flag so that it copies data from low memory address to high memory address. 36 00:03:35,390 --> 00:03:39,080 Then we move ecx edx 37 00:03:40,040 --> 00:03:47,560 and move al sil. Remember the first parameter is passed in register rdi, 38 00:03:47,560 --> 00:03:51,240 the second one in rsi and rdx rcx and so on. 39 00:03:51,700 --> 00:03:59,330 So rdi holds the address of the memory and the value we want to copy is in the second parameter. 40 00:03:59,330 --> 00:04:01,690 The third parameter is the size saved in rdx, 41 00:04:02,680 --> 00:04:10,620 the second parameter stores the value we want to copy which is 8 bits. We save it in al register. 42 00:04:10,630 --> 00:04:11,260 Then we write rep 43 00:04:12,660 --> 00:04:19,300 store byte which copy the value in al to the memory addressed by rdi register. 44 00:04:20,459 --> 00:04:22,560 After we set the memory,we can return. 45 00:04:25,120 --> 00:04:27,070 Next one is memory compare function. 46 00:04:30,260 --> 00:04:35,690 Also we execute cld instruction and then clear eax register 47 00:04:38,620 --> 00:04:46,530 which will save the return value. Just like we did in the memory set function, we move ecx edx. 48 00:04:48,190 --> 00:04:51,460 Edx stores the size. So we move it to ecx. 49 00:04:52,210 --> 00:04:55,480 OK, now we can repeat while equal 50 00:04:56,760 --> 00:04:58,650 and cmpsb 51 00:04:59,630 --> 00:05:05,900 which will compare memory and set eflags accordingly. If they are equal and ecx is non-zero, we will repeat the process 52 00:05:05,900 --> 00:05:06,960 . 53 00:05:07,250 --> 00:05:12,950 So if the zero flag is set after executing this instruction, we know that the result is equal. 54 00:05:13,470 --> 00:05:14,900 Othewise it’s not equal. 55 00:05:16,060 --> 00:05:20,590 Here we use set instruction, set if zero flag is cleared. 56 00:05:22,600 --> 00:05:28,930 So if zero flag is cleared, al is set to 1 which means the result is not equal. 57 00:05:28,930 --> 00:05:31,750 otherwise eax is zero meaning that the result is equal. 58 00:05:34,120 --> 00:05:35,290 And then we can return. 59 00:05:38,350 --> 00:05:41,110 The last function is memory move and copy, 60 00:05:42,550 --> 00:05:43,390 we define them 61 00:05:45,380 --> 00:05:46,340 as one function. 62 00:05:49,970 --> 00:05:55,940 When we copy data from one place to another, we actually have two situations, one is the two memory area are overlapped 63 00:05:55,940 --> 00:05:57,180 , 64 00:05:57,530 --> 00:06:00,030 another is these two are not overlapped. 65 00:06:00,470 --> 00:06:02,470 We have to deal with them in the function. 66 00:06:02,930 --> 00:06:09,120 If there is a scenario where the start of the source area is before the destination and the end is in the destination, 67 00:06:09,140 --> 00:06:12,740 we have to copy the data backward, 68 00:06:12,770 --> 00:06:15,510 that is, from the last data to the first data, 69 00:06:15,980 --> 00:06:20,310 otherwise the data at the back of the source will be replaced by the data in the front. 70 00:06:21,200 --> 00:06:25,400 As for other scenarios, we can simply copy data from the first to the last. 71 00:06:26,840 --> 00:06:28,790 So we need to check in the function. 72 00:06:30,480 --> 00:06:39,990 We compare rsi rdi. Rsi holds the address of the source and rdi holds the address of the destination. 73 00:06:39,990 --> 00:06:44,160 If rsi is greater than or equal to rdi, we just jmp to the copy part. 74 00:06:45,660 --> 00:06:46,860 So we define 75 00:06:47,990 --> 00:06:49,370 the local label copy 76 00:06:51,070 --> 00:06:56,410 If rsi is less than rdi, we will check to see if the end of the source is in the middle of the destination 77 00:06:56,410 --> 00:06:57,460 . 78 00:06:59,920 --> 00:07:02,620 The compare instruction we use is jae 79 00:07:06,630 --> 00:07:11,460 If rsi is less than rdi, we will check to see if the end of the source is in the middle of the destination 80 00:07:11,460 --> 00:07:12,410 . 81 00:07:12,870 --> 00:07:21,590 So we move r8 rsi and add r8 rdx which holds the value of size. 82 00:07:22,050 --> 00:07:23,730 now we compare r8 rdi. 83 00:07:27,070 --> 00:07:33,270 If r8 is less than or equal to rdi, we jump to the copy part. 84 00:07:34,090 --> 00:07:36,670 So the instruction we use is jbe. 85 00:07:41,060 --> 00:07:48,110 But if it is not, this is the situation we need to copy the data backward. So we define label overlap 86 00:07:50,370 --> 00:07:51,200 . 87 00:07:54,760 --> 00:07:57,370 and the first instruction is std 88 00:07:58,880 --> 00:08:05,540 set direction flag which will copy the data from high memory address to low memory address 89 00:08:05,540 --> 00:08:11,120 Then we adjust the rdi and rsi registers to the end of the destination and source 90 00:08:11,120 --> 00:08:13,280 so that we can copy data from the end to the start. 91 00:08:18,280 --> 00:08:20,740 And don't forget to decrement them by one. 92 00:08:27,240 --> 00:08:30,910 Otherwise we will end up 1 byte off from the correct position. 93 00:08:32,429 --> 00:08:36,650 Alright, now we can save the size in ecx. 94 00:08:38,480 --> 00:08:40,419 So we move ecx edx 95 00:08:42,020 --> 00:08:42,890 and repeat 96 00:08:44,900 --> 00:08:46,010 move byte 97 00:08:48,340 --> 00:08:54,160 which will copy the data from memory addressed by rsi to the memory addressed by rdi. 98 00:08:55,160 --> 00:09:00,830 When we finish, we write cld to clear the direction flag and return. 99 00:09:03,320 --> 00:09:04,450 OK, that's it. 100 00:09:05,420 --> 00:09:06,560 now we can add 101 00:09:11,020 --> 00:09:12,810 the lib file in the build script. 102 00:09:14,140 --> 00:09:15,340 The output file 103 00:09:19,180 --> 00:09:28,590 is called liba.o and the input file is lib.asm. We add it to the linker. 104 00:09:31,380 --> 00:09:31,790 OK. 105 00:09:33,110 --> 00:09:38,480 Because we haven't implemented print function, we don't test the functions in this lecture. 106 00:09:38,480 --> 00:09:42,530 In the next video, we will write our own print function and do the test after that.