[英]C Inline ASM: passing integers to a register
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. 我的函数,用于移动光标,是用汇编语言编写的,但是内核的其余部分都在C中,所以我必须为函数调用一个C函数。 And that's the C function: 这就是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");
}
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. 在这个函数中,我尝试将var unsigned int x
移动到寄存器bh
,将另一个unsigned int y
移动到寄存器bl
,然后调用该函数移动光标。
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. 我认为值x
和y
以及寄存器值bl
和bh
是不一样的。 For give you an idea of that clue, I tested to pass values directly in the asm directive and it works: 为了让您了解该线索,我测试了直接在asm指令中传递值,它可以工作:
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 :d
Assembly output from compiler Ubuntu 12.04 64bit compiling in 32bit 汇编输出编译器 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
Write the asm set_cursor function to use the CDECL calling convention and you can avoid the inline asm entirely. 编写asm set_cursor函数以使用CDECL调用约定,您可以完全避免使用内联asm。 Just use extern void set_cursor(int x, int y)
and you can call it like any other C function. 只需使用extern void set_cursor(int x, int y)
,就可以像任何其他C函数一样调用它。 I use this for all asm in my own "kernel" (LGDT/IDT/etc). 我在我自己的“内核”(LGDT / IDT / etc)中使用这个asm。 The only exception being setting cr3 for paging, since it's so simple. 唯一的例外是将cr3设置为分页,因为它非常简单。
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
In your code, you seem to be accessing the wrong variable with %0
, since the position 0 of variables has been skipped, and usualy, you must set =
to the destination variable. 在您的代码中,您似乎正在使用%0
访问错误的变量,因为已跳过变量的位置0,并且通常必须将=
设置为目标变量。
asm("mov (%1), %%bh" : : "r" (x) : "=bh");
|
%0 skipped
Also you can try to change the way you access registers: 您也可以尝试更改访问寄存器的方式:
register unsigned int *p0 asm ("r0") = x;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.