I was reading How to write a simple operating system, which says:
For your very first OS, you\'re better off sticking with assembly language, as used
In addition to dwelch's answer about doing initial setup, there are also some instructions and operations which are extremely specific to the processor architecture and do not belong in a portable language such as C.
For example, on x86 you need to enable protected mode or long mode, you need to set an Interrupt Descriptor table, you need to set up a Global Descriptor table - each one of these involve specialized instructions that only mean anything if you have an x86 CPU. It does not make sense to put these Intel-specific instructions into a programming language that might not need them when running on some other CPU. And of course those other CPUs have their own forms of the same concepts which do not apply at all to x86.
Another common use of assembly in a kernel is for atomic operations - though these are starting to make their way into higher-level language specs (C++11 comes to mind). Even still, the implementations of these will need to use assembly, and a kernel will want to have total control (you can't use some higher-level wait primitives that a usermode implementation might -- because in a new kernel these abstractions don't exist yet or even in the same form).