I'm trying to code the simplest of the kernels for 64 bits arch and I'm having trouble with keyboard input.
I'm currently implementing this two functions to manage 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));
}
But I'm getting this assembler error:
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»
Or in English:
main.c: Assembler messages:
main.c:51: Error: operand type mismatch for `in'
main.c:61: Error: operand type mismatch for `out'
My guess is that this code (that I got from http://www.osdever.net/bkerndev/Docs/creatingmain.htm) is designed for 32 bits assembly.
Any help on how to solve my problem would be greatly appreciated.
I build and run everything with this script
#!/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
By default GCC uses AT&T assembly syntax when generating assembly code from C code. This can be overridden by using the -masm=intel
GCC compile option. In the update to your question you have -masm=intel
in your GCC command line:
cc -m64 -masm=intel -c main.c
The code you found was designed for AT&T syntax where the source operand of an instruction is first and the destination is second. -masm=intel
option has reversed that behavior. You have two choices. Reverse the operands in the inline assembly so they are destination, source (intel syntax) like this:
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));
}
The other option is to remove -masm=intel
option from your GCC command line and keep the code as is. This might be preferable as a significant amount of OS Development code uses AT&T syntax for inline assembly.
Note: You might want to consider using gcc
instead of just cc