You do not call functions inside the kernel. The kernel resides in another privilege level; its memory pages are not accessible from normal code. To jump into kernel code, application code performs a system call which entails using a specific doorway which handles the temporary privilege escalation. On a 32-bit x86 system running Linux, this is done with
int 0x80: a software-triggered interrupt. The system call parameters are provided by the caller in some specific CPU registers; in particular, the
%eax register contains the symbolic identifier for the system call which the application wants to perform. The interruption handler (within the kernel) looks at the CPU registers to know what the application wants the kernel to do (whether the system call is granted is yet another issue).
There is no ASLR for system calls; this is not a relevant concept here. ASLR is for DLL. A DLL is a piece of application code which is loaded into the application address space and is accessible to the application under its normal privileges; in particular, the application code can "jump" into the DLL code with a normal "jump" opcode (a function call is nothing else than a glorified jump).
Since the actual address at which the DLL will be loaded is known only when the DLL is actually loaded, application code follows special conventions so that its jump opcodes can be dynamically adjusted to point to wherever the DLL happens to be loaded. This dynamic adjustment is performed by the dynamic linker. This linker uses relocation tables to perform its job: an entry in such a table describes an opcode which needs to be adjusted, and the name of the function which the opcode tries to reach. When the DLL is loaded (by the dynamic linker), the emplacement in memory of that function is known, and the jump opcodes described in the relocation tables are adjusted.
As you see, the whole concept of DLL allows for the DLL to be loaded at an arbitrary emplacement in RAM; that emplacement may differ upon successive executions of the application. The actual emplacement depends upon where there is a sufficiently large "hole" of free memory to do the loading, so it can change depending on what the application does, how much memory it allocates previously, and so on. DLL loading "naturally" implies non-fixed loading addresses. ASLR is just voluntary moving around of DLL: the dynamic linker chooses a random (free) loading address on purpose. This is (almost) completely transparent for the applications.