C Inline ASM:将整数传递给寄存器

时间:2014-04-18 19:12:35

标签: c assembly

我正在尝试创建一个简单的内核,但我仍然坚持使用光标屏幕移动。 我的函数,用于移动光标,是用汇编语言编写的,但是内核的其余部分都在C中,所以我必须为函数调用一个C函数。这就是C函数:

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");
}

在此函数中,我尝试将var unsigned int x移动到注册bh,将另一个unsigned int y移动到注册bl,然后调用该函数移动光标。

问题是当我调用此功能时,光标从屏幕上消失。我认为值xy以及值blbh的值不一样。为了让您了解该线索,我测试了直接在asm指令中传递值,它可以工作:

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

欢迎任何帮助。并提前感谢。 :d

编译器的汇编输出 Ubuntu 12.04 64位编译在32位

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

2 个答案:

答案 0 :(得分:4)

编写asm set_cursor函数以使用CDECL调用约定,您可以完全避免使用内联asm。只需使用extern void set_cursor(int x, int y),就可以像任何其他C函数一样调用它。我在我自己的内核中使用这个asm"内核" (LGDT / IDT /等)。唯一的例外是将cr3设置为分页,因为它非常简单。

假设使用英特尔语法,您可以添加:

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

答案 1 :(得分:0)

在您的代码中,您似乎使用%0访问了错误的变量,因为已跳过变量的位置0,并且通常必须将=设置为目标变量。

asm("mov (%1), %%bh" : : "r" (x) : "=bh");
                       |
                    %0 skipped

您也可以尝试更改访问寄存器的方式:

register unsigned int *p0 asm ("r0") = x;

了解更多here