Почему оператор + 1 увеличивается на 2 байта, а ++ увеличивается на 1 в C? - PullRequest
0 голосов
/ 03 мая 2019

Я пишу собственное ядро ​​и пытался записать видео по адресу 0xb8000.Наименее значимый байт - это символ ASCII, а наиболее значимый байт - это цвет фона / переднего плана.Вот мой код:

#define VIDEO_ADDRESS 0xb8000

void print_char(void) {
    char *vidmem = (char *)VIDEO_ADDRESS;

    // This produces a music note symbol instead of 'A'
    // the music symbol is probably represented by ascii 0x0E
    vidmem[0] = 0x41; //'A'
    vidmem[1] = 0x0E; //yellow on black

    /*
    // This also produces the undesired result above as expected
    // because this is equivalent to the above block of code
    *vidmem = 0x41;
    *(vidmem+1) = 0x0E;
    */

    /*
    // This produces a yellow 'A' on black background as expected.
    *vidmem = 0x41;
    vidmem++;
    *vidmem = 0x0E;
    */

    /*
    // This also produces the correct result (ie, 'A', yellow on black)
    *vidmem = 0x41; 
    vidmem = vidmem + 1;
    *vidmem = 0x0E;
    */
}

void kernel_entry() {
    print_char();
}

Код записи ядра сборки:

[bits 32]
[extern kernel_entry]
call kernel_entry
jmp $

Ко времени вызова kernel_entry() я уже настроил защищенный режим, поэтому я нахожусь в 32-битовый защищенный режим.

Мой Makefile показан ниже:

C_SOURCES = $(wildcard kernel/*.c drivers/*.c)
HEADERS = $(wildcard kernel/*.h drivers/*.h)

OBJ = ${C_SOURCES:.c=.o}

CC = gcc
CCFLAGS = -march=i386
LD = ld
AS = nasm
EMU = qemu-system-i386
#EMUFLAGS = -m 1024 -boot c -enable-kvm -smp 3
EMUFLAGS = -device isa-debug-exit,iobase=0xf4,iosize=0x04 -fda

all: minios

minios: boot/boot.bin kernel.bin
    cat $^ > minios

kernel.bin: kernel/kernel_entry.o ${OBJ}
    $(LD) -o $@ -Ttext 0x1000 $^ --oformat binary

%.o: %.c ${HEADERS}
    $(CC) -ffreestanding -c $< -o $@

%.o: %.asm
    $(AS) $< -f elf64 -o $@

%.bin: %.asm
    $(AS) $< -f bin -I '../../16bit/' -o $@

clean:
    rm -rf *.bin *.dis *.map *.o minios 
    rm -rf kernel/*.o boot/*.bin drivers/*.o

kernel.dis: kernel.bin
    ndisasm -b 64 $< > $@

run: all
    $(EMU) $(EMUFLAGS) minios

Мой вопрос: почему ++ не идентичен +1 в этом случае?Оператор ++ делает все правильно, так как он увеличивается на размер типа переменной (то есть char), но оператор +, похоже, увеличивается на 2 байта.Почему это так?

Ответы [ 2 ]

1 голос
/ 03 мая 2019

Если vidmem действительно определено как опубликованное, то нет никаких оснований для вычисления (vidmem+1) с использованием приращения 2 байта. Действительно, (vidmem+1) и vidmem++ должны иметь одинаковый эффект с точки зрения приращения байтов, даже идентификатор vidmem был определен с другим типом указателя данных, если это не void.

Обратите внимание, что макрос неправильный: вы должны удалить ; в конце #define VIDEO_ADDRESS 0xb8000;

Обратите внимание, что ваша функция также несовместима: если у вас есть все 4 опубликованных варианта, содержимое видеопамяти не будет таким, как закомментировано. Если вы просто перечисляете альтернативные тесты, которые вы пробовали, опубликуйте код для каждого теста отдельно с соответствующим наблюдением.

0 голосов
/ 04 мая 2019

Я нашел проблему.Я запускал 64-битный образ ядра на 32-битном эмуляторе QEMU.После кросс-компиляции всей сборки и исходного кода C с использованием компилятора 32 я могу видеть, что все работает как положено.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...