При компиляции inb и outb во встроенной сборке выдает «Ошибка: несоответствие типов операндов» - PullRequest
0 голосов
/ 27 октября 2018

Я пытаюсь кодировать самое простое из ядер для 64-битной арки, и у меня возникают проблемы с вводом с клавиатуры.

В настоящее время я реализую эти две функции для управления вводом / выводом

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

1 Ответ

0 голосов
/ 27 октября 2018

По умолчанию GCC использует синтаксис сборки AT & T при генерации кода сборки из кода C .Это можно изменить, используя опцию компиляции -masm=intel GCC .В обновлении вашего вопроса у вас есть -masm=intel в командной строке GCC :

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));
}

Другой вариант - удалить опцию -masm=intel из командной строки GCC и сохранить код как есть.,Это может быть предпочтительным, так как значительный объем кода разработки ОС использует синтаксис AT & T для встроенной сборки.


Примечание. Возможно, вы захотите использовать gcc вместо просто cc

...