Hello, everyone.
in this lecture we will write our own library functions used in the kernel, such as memory copy,
memory set, etc.
The file is called lib.
We create
a new file
call lib.h
Just like we did before, we create a guard.
So if this label is not defined, we define it.
The first function is memory set which is pretty much the same as the one in c standard library.
In our memory set function, we return no value and the first parameter is the address of the memory being set.
The second parameter is the value we want to set the memory with.
The size of the memory we want to set is specified in the last parameter.
OK, the next two functions are related to the memory copy.
The memory move
and memory copy
.
They are the same function in our system.
The first parameter of the function is destination
and the source is stored in the second parameter.
The last parameter stores the size of bytes need copying.
The last function is memory compare. Unlike the above functions,
it returns an integer. Here if the return value is 0, it means the result of comparison is equal.
Otherwise they are not equal.
The first two parameters are the addresses of two memory areas being compared.
The size is specified in the last parameter.
Ok, for now we only implement these four functions. We will add more functions as we move on.
And also these functions are implemented using assembly language, since we have the corresponding instructions
to perform the tasks.
So we create assembly file.
We call it lib.asm
In the text section,
we declare the functions globally so that we can use them in the C files.
Ok now we write memory set function. So we define label memset. We use instruction cld
which clears the direction flag so that it copies data from low memory address to high memory address.
Then we move ecx edx
and move al sil. Remember the first parameter is passed in register rdi,
the second one in rsi and rdx rcx and so on.
So rdi holds the address of the memory and the value we want to copy is in the second parameter.
The third parameter is the size saved in rdx,
the second parameter stores the value we want to copy which is 8 bits. We save it in al register.
Then we write rep
store byte which copy the value in al to the memory addressed by rdi register.
After we set the memory,we can return.
Next one is memory compare function.
Also we execute cld instruction and then clear eax register
which will save the return value. Just like we did in the memory set function, we move ecx edx.
Edx stores the size. So we move it to ecx.
OK, now we can repeat while equal
and cmpsb
which will compare memory and set eflags accordingly. If they are equal and ecx is non-zero, we will repeat the process
.
So if the zero flag is set after executing this instruction, we know that the result is equal.
Othewise it�s not equal.
Here we use set instruction, set if zero flag is cleared.
So if zero flag is cleared, al is set to 1 which means the result is not equal.
otherwise eax is zero meaning that the result is equal.
And then we can return.
The last function is memory move and copy,
we define them
as one function.
When we copy data from one place to another, we actually have two situations, one is the two memory area are overlapped
,
another is these two are not overlapped.
We have to deal with them in the function.
If there is a scenario where the start of the source area is before the destination and the end is in the destination,
we have to copy the data backward,
that is, from the last data to the first data,
otherwise the data at the back of the source will be replaced by the data in the front.
As for other scenarios, we can simply copy data from the first to the last.
So we need to check in the function.
We compare rsi rdi. Rsi holds the address of the source and rdi holds the address of the destination.
If rsi is greater than or equal to rdi, we just jmp to the copy part.
So we define
the local label copy
If rsi is less than rdi, we will check to see if the end of the source is in the middle of the destination
.
The compare instruction we use is jae
If rsi is less than rdi, we will check to see if the end of the source is in the middle of the destination
.
So we move r8 rsi and add r8 rdx which holds the value of size.
now we compare r8 rdi.
If r8 is less than or equal to rdi, we jump to the copy part.
So the instruction we use is jbe.
But if it is not, this is the situation we need to copy the data backward. So we define label overlap
.
and the first instruction is std
set direction flag which will copy the data from high memory address to low memory address
Then we adjust the rdi and rsi registers to the end of the destination and source
so that we can copy data from the end to the start.
And don't forget to decrement them by one.
Otherwise we will end up 1 byte off from the correct position.
Alright, now we can save the size in ecx.
So we move ecx edx
and repeat
move byte
which will copy the data from memory addressed by rsi to the memory addressed by rdi.
When we finish, we write cld to clear the direction flag and return.
OK, that's it.
now we can add
the lib file in the build script.
The output file
is called liba.o and the input file is lib.asm. We add it to the linker.
OK.
Because we haven't implemented print function, we don't test the functions in this lecture.
In the next video, we will write our own print function and do the test after that.