Page 1 of 1

How does interrupt handlers call C

Posted: Tue Jun 24, 2014 3:11 pm
by icealys
when a software interrupt passes the parameters in the registers, how does the ISR get the data from those registers and pass them to a winapi function in the kernel? Is there assembly language involved ? Basically I want a code example of how these steps are accomplished.

1. When the ISR recieves parameters from the registers.
2. passing the parameters it recieves to the winapi function in the kernel.

Re: How does interrupt handlers call C

Posted: Tue Jun 24, 2014 5:08 pm
by sortie
There is no WINAPI calling convention, that is just a macro that expands to the __stdcall Microsoft calling convention. I'm assuming you are still trying to take over the Windows kernel interrupt handler to do crazy stuff?

You should read the Intel/AMD CPU documentation to learn how interrupt handlers work. They push values to the stack, they don't touch any registers besides esp, eflags and eip, the rest is up to the kernel to save. My WIP example tutorial kernel demonstrates how to call a kernel function written in the System V ABI from an assembly interrupt handler. Since you use the __stdcall calling calling convention instead, you will want to look up the specifics and adapt them, it is mostly the same but not quite.

Re: How does interrupt handlers call C

Posted: Tue Jun 24, 2014 5:20 pm
by AndrewAPrice
You will be interested in reading this: http://en.m.wikipedia.org/wiki/X86_calling_conventions

Re: How does interrupt handlers call C

Posted: Tue Jun 24, 2014 7:40 pm
by BASICFreak
Something like this Broken Thorn User Land Tutorial where you can send a whole function like printf_INT(const char *MSG, ...)

or something similar to what I use just to pass registers to INT handler for user apps (at least for now)

Code: Select all

typedef struct INT_registers	{
		uint32_t gs, fs, es, ds;
		uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax;
		uint32_t INTnum;
		uint32_t eip, cs, eflags, useresp, ss;    
	} INTregs;

Code: Select all

_INT0:
    cli
    push byte 0
    jmp INT_COMMON

INT_COMMON:
    pusha
    push ds
    push es
    push fs
    push gs
    mov ax, 0x10
    mov ds, ax
    mov es, ax
    mov fs, ax
    mov gs, ax
    mov eax, esp
    push eax
    mov eax, _INT_HANDLER
    call eax
    pop eax
    pop gs
    pop fs
    pop es
    pop ds
    popa
    add esp, 8
    iret
and I have a function void _INT_HANDLER(INTregs *r) in C which determines which function the INT goes to and forwards a pointer to stack with registers. The IDT entry for INT 0x30 (in my case) points to _INT0

Which you can still pass the entirety of the data if you read how C functions are laid out This may be very useful to you.


Best of luck
- Brian

Re: How does interrupt handlers call C

Posted: Tue Jun 24, 2014 11:55 pm
by icealys
so does the processor somehow push the parameters onto the stack when it calls the interrupt handler? I thought that would be impossible since you need to implement a push operation in code by calling a function like this ...int somefunc(param1,param2);. So my question is, can the processor push the parameters on its own when it calls the interrupt handler?

Re: How does interrupt handlers call C

Posted: Wed Jun 25, 2014 12:04 am
by BASICFreak
icealys wrote:so does the processor somehow push the parameters onto the stack when it calls the interrupt handler? I thought that would be impossible since you need to implement a push operation in code by calling a function like this ...int somefunc(param1,param2);. So my question is, can the processor push the parameters on its own when it calls the interrupt handler?
The Processor pushes eip, cs, eflags, useresp, and ss on int/irq/isr call

Then I push INT# byte

pusha then pushes edi, esi, ebp, esp, ebx, edx, ecx, and eax

and I also push gs, fs, es, and ds just in case I want to change tasks while in the INT (but thats just me) would be faster (not by much) without

Re: How does interrupt handlers call C

Posted: Wed Jun 25, 2014 12:29 am
by bluemoon
icealys wrote:so does the processor somehow push the parameters onto the stack when it calls the interrupt handler? I thought that would be impossible since you need to implement a push operation in code by calling a function like this ...int somefunc(param1,param2);. So my question is, can the processor push the parameters on its own when it calls the interrupt handler?
There are basically 3 parts for system call:
1. gathering parameters in user-space
2. invoke the kernel
3. get those parameters in kernel-space
3.5 system handler stub invoke C/C++/Higher level handlers

Generally you need to define how to pass parameters from (1) to (3), the CPU won't do anything magically except those defined in the manual.
Most design just pass parameters on registers, i.e.

In step 1 your user-space syscall function may do:
- preserve registers requested by ABI
- put parameters to registers, in some design you may also pass parameters on stack or indirect pointer to memory

Then, for (2) invoke the kernel with INT, SYSENTER, SYSCALL or other ridiculous ways. Note that some mechanic involve stack switch.

In (3), the stub would:
- preserve registers requested by syscall ABI, or just preserve none, or all.
- extract the parameters
- invoke high-level handlers according to ABI


Now this seems bloated, but on smartly designed ABI like AMD x86_64, all the register preservation is eliminated and things reduced to:

Code: Select all

; USER SPACE API
; int open ( const char * file, int flags, int mode );
open:
    mov     eax, 2
    mov     r10, rcx    ; rcx is used by syscall
    syscall
    ret

-----------------------------------------
KERNEL STUB (simplified)
_syscall_stub:
    cmp     rax, 12
    ja      .fault

    mov     r10, rsp
    mov     rsp, qword [k_TSS + tss64_rsp0]     ; switch to kernel stack
    sti

    push    rcx                                 ; userspace rip
    push    r11                                 ; rflags
    push    r10                                 ; user stack

    mov     r11, qword syscall_table
    mov     rcx, r9                             ; 4th parameter

    ; invoke handler
    call    qword [r11 + rax*8]

    pop     r10
    pop     r11
    pop     rcx

    cli
    mov     rsp, r10
    db 0x48 ; REX.w
    sysret
    
.fault:
    mov     eax, -1
    db 0x48 ; REX.w
    sysret

-----------------------------------------
KERNEL HANDLER (simplified)
int kservice_open(const char * file, int flags, int mode) {
    kprintf ( "SYSCALL : open(%s, %X, %X)\n", file, flags, mode );
    return -1;
}


Re: How does interrupt handlers call C

Posted: Wed Jun 25, 2014 5:20 am
by sortie
Read the Intel/AMD CPU documentation on interrupts.

Re: How does interrupt handlers call C

Posted: Sat Jul 05, 2014 1:55 am
by Gigasoft
BasicFREAK wrote:Something like this Broken Thorn User Land Tutorial
I really wouldn't recommend taking the BrokenThorn tutorial seriously. As the name implies, it's completely broken.

For example, on the page you linked to, he sets FS and GS to 0x23 for no reason. He also enters user mode with interrupts disabled. The whole "enter_usermode" concept is flawed - no operating system would work this way, ever. Making the kernel stack writeable in user mode is as good as not having user mode at all. Later, he sets some segment register fields in a TSS, again for no reason as they are not used for anything.