Search code examples
cassemblykeyboardinterrupt-handlingminix

Interrupt handler in ASM/C - How to? -Minix


I've been programming hardware (mouse, keyboard etc) in the Unix OS, Minix and I came across with a few problems when prompted to combine it with Assembly (AT&T syntax).

As of now I'm programming the keyboard (getting and printing the scan codes), and I'm required to do it both in C and ASM. I've already developed the C function which is working correctly and now I must replace the IH (interrupt handler) with a ASM function(s), as the following code specifies: (The code to be replaced is in the function "receiver_loop")

int timer_subscribe_int(void ) {

    int temp = hook_id; //integer between 0 and 31
    sys_irqsetpolicy(TIMER0_IRQ, IRQ_REENABLE,&hook_id); // returns a hook id that you can then use to enable and disable irqs.
    sys_irqenable(&hook_id);
    return temp;
}

int timer_unsubscribe_int() {

    if (sys_irqrmpolicy(&hook_id)!= OK) return 1;
    return 0;
}


void receiver_loop() {

    int ipc_status,r, seconds = 0, running = 1;
    message msg;

    int shift = keyboard_subscribe_int();
    int shift_timer;
    if(timer_flag) shift_timer = timer_subscribe_int();

        while(running && (seconds < time)) {
            /* Get a request message. */
            if ( driver_receive(ANY, &msg, &ipc_status) != 0 ) {
                printf("driver_receive failed with: %d", r);
                continue;
            }
            if (is_ipc_notify(ipc_status)) { /* received notification */
                switch (_ENDPOINT_P(msg.m_source)) {
                case HARDWARE: /* hardware interrupt notification */
                    if (msg.NOTIFY_ARG & BIT(shift)) { /* subscribed interrupt  bit 1 fica a 1, logo é 1*/

                    // Handle interruption
                     /*Replace the following commented code with ASM function(s)

                        if(keyboard_int_handler()) running = 0;
                        else seconds = 0;

                    }

                    else if (msg.NOTIFY_ARG & BIT(shift_timer) && timer_flag) { // subscribed interrupt  bit 1 fica a 1, logo é 1
                        //printf("\n Entrou aqui. Counter %d \n", counter);
                        timer_int_handler();
                        if (counter%60 == 0){
                            //as the frequency of interruptions is 60Hz as assumed, that means every 60 interrupts 1 second has passed
                            //so whatever is inside this if-block happens each second
                            seconds++; // increments the seconds counter
                            //printf("\n Segundos: %d \n", seconds);
                    };*/
                }
                break;
            default:
                break; /* no other notifications expected: do nothing */
            }
        } else { /* received a standard message, not a notification */
            /* no standard messages expected: do nothing */
        }
    }

    if(seconds >= time) {
        printf("\nTimeout. Terminating...\n");
    }


    keyboard_unsubscribe_int();
    timer_unsubscribe_int();
    return;
}

This is what I got so far, and to be honest I'm sort of stuck on how to go from here and get a similar ASM function to replace the commented code. Can anyone give me a hand?


Solution

  • gcc provides a simple way to take your c code and output the related assembler. So if you need to turn some c code into assembler. A simple approach would look something like this:

    1. Start by localizing the code into a single routine.
    2. Mark this routine with __attribute__((noinline)) to prevent gcc from inlining your routine into other routines. While normally inlining is a good thing which makes your code run faster, if you are trying to isolate specific code, that's not what you need.
    3. Compile the code with a command line like: gcc -S -o test.s test.c. Note that you can (and probably should) turn on optimizations (gcc -O2 -S -o test.s test.c).
    4. The assembly for test.c is now in test.s. Examine it to find your routine.

    Note that by default, the output on i386 will be in att format. If you prefer intel format, you can use -masm=intel.