GCC裸机内联汇编SI寄存器不能很好地与指针一起玩 [英] GCC baremetal inline-assembly SI register not playing nicely with pointers

查看:226
本文介绍了GCC裸机内联汇编SI寄存器不能很好地与指针一起玩的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

好了,这显然是一个初学者的问题,但这是我第一次尝试在 C 中创建一个操作系统(实际上,我几乎是全新的 C ..我习惯于 asm )所以,为什么这是无效的?据我所知, C 中的指针只是 uint16_t 用于指向内存中的某个区域,右(或者 uint32_t ,这就是为什么它不起作用)?
我创建了以下内核(我已经创建了一个bootloader,并且所有程序集都加载了生成的KERNEL.BIN文件):

kernel.c

  void printf(char * str)
{
__asm __(
mov si,%0\\\

pusha \\\

mov ah,0x0E\\\

。重复:\\\

lodsb\\\

cmp al,0\\\

je .done\\\

int 0x10 \ n
jmp .repeat \\\

.done:\\\

popa\\\


:r( str)
);
return;
}

int main()
{
char * msg =Hello,world! ;
printf(msg);
__asm __(jmp $);
return 0;
}

我用下面的命令编译它 kernel.c



gcc kernel.c -freestanding -m32 -std = c99 -g -O0 -masm = intel -o kernel.bin



会返回以下错误:

kernel.c:3:错误:opera 'mov'的类型不匹配



为什么会出现这种错误?



总是让GCC完成将值传递给正确寄存器的工作,并且只需指定值应该在哪个寄存器中是。



对于你的问题,你可能想要做这样的事情

  #include< stdint.h> 

void print(const char * str)
{
for(; * str; str ++){
__asm__ __volatile __(int $ 0x10:a ((int16_t)((0x0E <= 8)+ * str)),b((int16_t)0):);


编辑:您的程序集有问题,您尝试在一个16位寄存器中传递一个指针。这不适用于32位代码,因为32位也是指针大小。
如果您想要生成16位实模式代码,则有-m16选项。但是这并不能使GCC成为真正的16位编译器,它有其局限性。本质上,它在代码中发布.code16gcc指令。


Well, this is obviously a beginner's question, but this is my first attempt at making an operating system in C (Actually, I'm almost entirely new to C.. I'm used to asm) so, why exactly is this not valid? As far as I know, a pointer in C is just a uint16_t used to point to a certain area in memory, right (or a uint32_t and that's why it's not working)? I've made the following kernel ("I've already made a bootloader and all in assembly to load the resulting KERNEL.BIN file):

kernel.c

void printf(char *str)
{
__asm__(
"mov    si, %0\n"
"pusha\n"
"mov    ah, 0x0E\n"
".repeat:\n"
"lodsb\n"
"cmp    al, 0\n"
"je .done\n"
"int    0x10\n"
"jmp    .repeat\n"
".done:\n"
"popa\n"
:
: "r" (str)
);
return;
}

int main()
{
char *msg = "Hello, world!";
printf(msg);
__asm__("jmp $");
return 0;
}

I've used the following command to compile it kernel.c:

gcc kernel.c -ffreestanding -m32 -std=c99 -g -O0 -masm=intel -o kernel.bin

which returns the following error:

kernel.c:3: Error: operand type mismatch for 'mov'

Why exactly might be the cause of this error?

解决方案

As Michael Petch already explained, you use inline assembly only for the absolute minimum of code that cannot be done in C. For the rest there is inline assembly, but you have to be extremely careful to set the constraints and clobber list right.

Let always GCC do the job of passing the values in the right register and just specify in which register the values should be.

For your problem you probably want to do something like this

#include <stdint.h>

void print( const char *str )
{
  for ( ; *str; str++) {
    __asm__ __volatile__("int $0x10" : : "a" ((int16_t)((0x0E << 8) + *str)), "b" ((int16_t)0) : );
  }
}

EDIT: Your assembly has the problem that you try to pass a pointer in a 16 bit register. This cannot work for 32 bit code, as 32 bit is also the pointer size. If you in case want to generate 16 bit real-mode code, there is the -m16 option. But that does not make GCC a true 16 bit compiler, it has its limitations. Essentially it issues a .code16gcc directive in the code.

这篇关于GCC裸机内联汇编SI寄存器不能很好地与指针一起玩的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆