Stylistically, there are a huge number of things wrong with this. The idea is good, but if you actually write code this way you'll have a slow, unmaintainable mess of a kernel.
The biggest issues that jump out at me are the horrible overuse of magic numbers (#define is your friend, especially when working with the GDT and IDT) and the disabling of interrupts and paging when copying an address space (the latter of which is slow and the former of which prevents concurrency -- imagine how well Linux would work if every fork() were terribly slow and stopped the world -- doing this in even a halfway reasonable way is not hard). Inline assembly is also a really bad idea for portability and maintainability, the latter of which you at least care about for a toy kernel. I'm also not sure why they are disabling interrupts so much in general... and on and on.
Again, a very interesting read for kernel-development-n00bs, I'm sure, but a lot of their code is very, very, terrifyingly wrong even for a toy kernel. Our OS class has students write a kernel somewhat like this one; the class provides a list of things which you are not to ever do, ever, oh god, or you will fail. This article does a staggering number of those things.
I know, there are some seriously bad stylistic mistakes in that code, as well as doing some things "the wrong way" (stack move instead of a recursive page directory is a prime example).
The tutorial series was written in 2007, so quite a time ago. I got around to rewriting the code, but not the overlaying documentation and explanation so the old version is still live.
It should also be noted that my tutorial series was not designed to teach people "how to write a kernel" - more to show how to bridge the gap between theory and practice. There are many books and resources (Tanenbaum's book is an example) that deals purely with theory - algorithms used etc.
There are also many resources about assembler programming and C, but to my knowledge not really many that showed how to apply the theory, concrete it and end up with "something" that runs (which can then ideally be adapted based on better theory).
Do you know of anything we can have a look at which gives a better overview of kernel architecture?
I am really more interested in learning more about good kernel architecture and rolling one the "Right Way" than I am in getting a working but crappy kernel.
It's a C issue, not an implementation issue. Learn C well.
Alternatively, study OS kernels not implemented in C. It's all basic algorithms and can be implemented in any language, if you content with abstraction and don't mind working with emulated "devices".
While the example code is horrible in many ways, this is the best tutorial I've seen theory-wise (although that's not counting the Minix book since I haven't been able to read that yet).
If you have any experience programming in C, which you should if you're attempting this, the horribleness is somewhat forgivable, and it's a good experience trying to write it on a nicer way, debugging your own kernel code, etc.
The biggest issues that jump out at me are the horrible overuse of magic numbers (#define is your friend, especially when working with the GDT and IDT) and the disabling of interrupts and paging when copying an address space (the latter of which is slow and the former of which prevents concurrency -- imagine how well Linux would work if every fork() were terribly slow and stopped the world -- doing this in even a halfway reasonable way is not hard). Inline assembly is also a really bad idea for portability and maintainability, the latter of which you at least care about for a toy kernel. I'm also not sure why they are disabling interrupts so much in general... and on and on.
Again, a very interesting read for kernel-development-n00bs, I'm sure, but a lot of their code is very, very, terrifyingly wrong even for a toy kernel. Our OS class has students write a kernel somewhat like this one; the class provides a list of things which you are not to ever do, ever, oh god, or you will fail. This article does a staggering number of those things.