По какой-либо причине следующая встроенная сборка (стиль AT & T / gcc) не работает на недавно установленной 64-битной машине Debian GNU / Linux; он компилируется и корректно работает на других машинах:
static void INIT_CODE kernel_entry (void) NORETURN;
void _start(void)
{
// ...other code here...
asm ("ljmp %0, %1"
:
: "n" (SELECTOR_KERNEL_CODE),
"p" (&kernel_entry));
}
static void INIT_CODE kernel_entry(void)
{
// ...
}
Я получаю ошибку компиляции с gcc 7 и 8:
$ gcc-7 -o init.o -Wall -Wextra -Wshadow -Wpointer-arith -Waggregate-return \
-Wredundant-decls -Winline -Werror -Wcast-align -Wsign-compare -Wmissing-declarations \
-Wmissing-noreturn -pipe -O0 -fno-builtin -fno-asynchronous-unwind-tables \
-funsigned-char -g -fomit-frame-pointer -ffreestanding -DPACKAGE_NAME=\"storm\" \
-DPACKAGE_VERSION=\"0.5.1+\" \
-DREVISION=\"`git rev-list HEAD --max-count 1 --abbrev-commit`\" \
-DCREATOR=\"`whoami`@`hostname -s`\" --std=gnu99 -Wbad-function-cast \
-Wmissing-prototypes -Wnested-externs -Wstrict-prototypes -m32 -I../include \
-I.. -I. -c init.c
init.c: Assembler messages:
init.c:151: Error: operand type mismatch for `ljmp'
Я также попытался просмотреть код сборки (скомпилировать с -S
), и вполне понятно, почему он не компилируется:
#NO_APP
leal kernel_entry@GOTOFF(%eax), %eax
#APP
# 151 "init.c" 1
ljmp $8, %eax
# 0 "" 2
Это не будет работать; инструкция ljmp
принимает только два постоянных операнда (т.е. не %eax
в качестве второго операнда).
Итак, как я могу gcc
понять это? Нужно ли менять ограничение аргумента p
? Я уже пытался изменить его на n
, но вместо этого я получаю эту ошибку:
init.c: In function ‘_start’:
init.c:151:5: warning: asm operand 1 probably doesn’t match constraints
asm ("ljmp %0, %1"
^~~
init.c:151:5: error: impossible constraint in ‘asm’
Большое спасибо заранее.