我正在尝试制作一个简单的内核,但我卡在了光标屏幕移动上。 我的移动光标函数是用汇编语言编写的,但内核的其余部分是用 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
,然后调用移动光标的函数。
问题是当我调用这个函数时,光标从屏幕上消失了。我认为值 x
和 y
以及寄存器值 bl
和 bh
是不一样的。为了让您了解该线索,我测试了直接在 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
最佳答案
编写 asm set_cursor 函数以使用 CDECL 调用约定,您可以完全避免内联 asm。只需使用 extern void set_cursor(int x, int y)
,您就可以像调用任何其他 C 函数一样调用它。我将它用于我自己的“内核”(LGDT/IDT/等)中的所有 asm。唯一的异常(exception)是为分页设置 cr3,因为它非常简单。
假设使用 Intel 语法,您可以添加:
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
关于C 内联 ASM : passing integers to a register,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23160655/