![](/img/trans.png)
[英]Call C function from asm file by passing function address in a register
[英]C Inline ASM: passing integers to a register
我正在尝试制作一个简单的内核,但我仍然坚持使用光标屏幕。 我的函数,用于移动光标,是用汇编语言编写的,但是内核的其余部分都在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 / etc)中使用这个asm。 唯一的例外是将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
在您的代码中,您似乎正在使用%0
访问错误的变量,因为已跳过变量的位置0,并且通常必须将=
设置为目标变量。
asm("mov (%1), %%bh" : : "r" (x) : "=bh");
|
%0 skipped
您也可以尝试更改访问寄存器的方式:
register unsigned int *p0 asm ("r0") = x;
在这里阅读更多。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.