When compiled inb and outb in inline assembly produce "Error: operand type mismatch"
When compiled inb and outb in inline assembly produce "Error: operand type mismatch"
我正在尝试为 64 位 arch 编写最简单的内核代码,但我在键盘输入方面遇到了问题。
我目前正在实现这两个功能来管理I/O
unsigned char inportb (unsigned short _port)
{
unsigned char rv;
__asm__ __volatile__ ("inb %1, %0" : "=a" (rv) : "dN" (_port));
return rv;
}
void outportb (unsigned short _port, unsigned char _data)
{
__asm__ __volatile__ ("outb %1, %0" : : "dN" (_port), "a" (_data));
}
但是我遇到了这个汇编错误:
main.c: Mensajes del ensamblador:
main.c:51: Error: no coincide el tipo de operando para «in»
main.c:61: Error: no coincide el tipo de operando para «out»
或英文:
main.c: Assembler messages:
main.c:51: Error: operand type mismatch for `in'
main.c:61: Error: operand type mismatch for `out'
我猜这个代码(我从 http://www.osdever.net/bkerndev/Docs/creatingmain.htm 得到的)是为 32 位汇编设计的。
如能帮助解决我的问题,我们将不胜感激。
我用这个脚本构建并运行一切
#!/bin/bash
nasm -f bin boot.asm -o boot.bin
nasm -f elf64 loader.asm -o loader.o
#cc -m64 -ffreestanding -fno-builtin -nostdlib -c main.c
cc -m64 -masm=intel -c main.c
ld -Ttext 0x100000 -o kernel.elf loader.o main.o
objcopy -R .note -R .comment -S -O binary kernel.elf kernel.bin
dd if=/dev/zero of=image.bin bs=512 count=2880
dd if=boot.bin of=image.bin conv=notrunc
dd if=kernel.bin of=image.bin conv=notrunc bs=512 seek=1
rm ./boot.bin ./kernel.bin ./main.o ./loader.o ./kernel.elf
qemu-system-x86_64 image.bin
默认情况下,GCC 在从 C 代码生成汇编代码时使用 AT&T 汇编语法。这可以通过使用 -masm=intel
GCC 编译选项来覆盖。在您的问题的更新中,您的 GCC 命令行中有 -masm=intel
:
cc -m64 -masm=intel -c main.c
您找到的代码是为 AT&T 语法设计的,其中指令的源操作数在前,目标在后。 -masm=intel
选项已逆转该行为。你有两个选择。反转内联汇编中的操作数,使它们分别是目标、源(intel 语法),如下所示:
unsigned char inportb (unsigned short _port)
{
unsigned char rv;
__asm__ __volatile__ ("inb %0, %1" : "=a" (rv) : "dN" (_port));
return rv;
}
void outportb (unsigned short _port, unsigned char _data)
{
__asm__ __volatile__ ("outb %0, %1" : : "dN" (_port), "a" (_data));
}
另一个选项是从 GCC 命令行中删除 -masm=intel
选项并保持代码不变。这可能更可取,因为大量 OS 开发代码使用 AT&T 语法进行内联汇编。
注意:您可能需要考虑使用 gcc
而不是 cc
我正在尝试为 64 位 arch 编写最简单的内核代码,但我在键盘输入方面遇到了问题。
我目前正在实现这两个功能来管理I/O
unsigned char inportb (unsigned short _port)
{
unsigned char rv;
__asm__ __volatile__ ("inb %1, %0" : "=a" (rv) : "dN" (_port));
return rv;
}
void outportb (unsigned short _port, unsigned char _data)
{
__asm__ __volatile__ ("outb %1, %0" : : "dN" (_port), "a" (_data));
}
但是我遇到了这个汇编错误:
main.c: Mensajes del ensamblador:
main.c:51: Error: no coincide el tipo de operando para «in»
main.c:61: Error: no coincide el tipo de operando para «out»
或英文:
main.c: Assembler messages:
main.c:51: Error: operand type mismatch for `in'
main.c:61: Error: operand type mismatch for `out'
我猜这个代码(我从 http://www.osdever.net/bkerndev/Docs/creatingmain.htm 得到的)是为 32 位汇编设计的。
如能帮助解决我的问题,我们将不胜感激。
我用这个脚本构建并运行一切
#!/bin/bash
nasm -f bin boot.asm -o boot.bin
nasm -f elf64 loader.asm -o loader.o
#cc -m64 -ffreestanding -fno-builtin -nostdlib -c main.c
cc -m64 -masm=intel -c main.c
ld -Ttext 0x100000 -o kernel.elf loader.o main.o
objcopy -R .note -R .comment -S -O binary kernel.elf kernel.bin
dd if=/dev/zero of=image.bin bs=512 count=2880
dd if=boot.bin of=image.bin conv=notrunc
dd if=kernel.bin of=image.bin conv=notrunc bs=512 seek=1
rm ./boot.bin ./kernel.bin ./main.o ./loader.o ./kernel.elf
qemu-system-x86_64 image.bin
默认情况下,GCC 在从 C 代码生成汇编代码时使用 AT&T 汇编语法。这可以通过使用 -masm=intel
GCC 编译选项来覆盖。在您的问题的更新中,您的 GCC 命令行中有 -masm=intel
:
cc -m64 -masm=intel -c main.c
您找到的代码是为 AT&T 语法设计的,其中指令的源操作数在前,目标在后。 -masm=intel
选项已逆转该行为。你有两个选择。反转内联汇编中的操作数,使它们分别是目标、源(intel 语法),如下所示:
unsigned char inportb (unsigned short _port)
{
unsigned char rv;
__asm__ __volatile__ ("inb %0, %1" : "=a" (rv) : "dN" (_port));
return rv;
}
void outportb (unsigned short _port, unsigned char _data)
{
__asm__ __volatile__ ("outb %0, %1" : : "dN" (_port), "a" (_data));
}
另一个选项是从 GCC 命令行中删除 -masm=intel
选项并保持代码不变。这可能更可取,因为大量 OS 开发代码使用 AT&T 语法进行内联汇编。
注意:您可能需要考虑使用 gcc
而不是 cc