Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C Inline ASM: passing integers to a register

Tags:

c

assembly

I'm trying to make a simple kernel but I'm stucked on a cursor screen movement. My function, for move the cursor, is written in Assembly, but the rest of the kernel is in C, so I have to make a C function for call that function. And that's the C function:

void setCursor(unsigned int x, unsigned int y) {
    asm("mov (%0), %%bl" :: "r" (y) : "%bl");
    asm("mov (%0), %%bh" :: "r" (x) : "%bh");
    asm("call set_cursor");
}

In this function, I try to move the var unsigned int x to register bh and the other, unsigned int y, to register bl, and then call the function to move the cursor.

The problem is when I call this function, the cursor disappear from the screen. I think the values x and y and registers values bl and bh are not the same. For give you an idea of that clue, I tested to pass values directly in the asm directive and it works:

void setCursor(unsigned int x, unsigned int y) {
    asm("mov $1, %bl");
    asm("mov $2, %bh");
    asm("call set_cursor");
}

Any help is welcome. And thanks in advance. :D

Assembly output from compiler Ubuntu 12.04 64bit compiling in 32bit

setCursor:
.LFB12:
    .cfi_startproc
    pushl   %ebp
    .cfi_def_cfa_offset 8
    .cfi_offset 5, -8
    movl    %esp, %ebp
    .cfi_def_cfa_register 5
    movl    12(%ebp), %eax
    pushl   %ebx
    .cfi_offset 3, -12
#APP
# 131 "./kernel/screen.c" 1
    mov (%eax), %bl
# 0 "" 2
#NO_APP
    movl    8(%ebp), %eax
#APP
# 132 "./kernel/screen.c" 1
    mov (%eax), %bh
# 0 "" 2
# 133 "./kernel/screen.c" 1
    call set_cursor
# 0 "" 2
#NO_APP
    popl    %ebx
    .cfi_restore 3
    popl    %ebp
    .cfi_def_cfa 4, 4
    .cfi_restore 5
    ret
    .cfi_endproc
like image 591
melchor629 Avatar asked Nov 27 '25 07:11

melchor629


1 Answers

Write the asm set_cursor function to use the CDECL calling convention and you can avoid the inline asm entirely. Just use extern void set_cursor(int x, int y) and you can call it like any other C function. I use this for all asm in my own "kernel" (LGDT/IDT/etc). The only exception being setting cr3 for paging, since it's so simple.

Assuming Intel syntax, you could add:

set_cursor:
   mov     ecx, [esp + 4] # x in ecx (args are pushed right to left)
   mov     edx, [esp + 8] # y in edx

   push    ebx            # ebx has to be preserved in CDECL

   mov     bh, cl
   mov     bl, dl

   # Your original code...

   pop     ebx
   ret
like image 96
Tyler Avatar answered Nov 28 '25 22:11

Tyler



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!