This thread is ancient. I hope that you already found an answer. Anyways I am writing for people who are having the same question.

After you are done setting up gdt and switching to protected mode.
Jmp to a memory location like, jmp 0x8000 in your assembly. Assemble to generate boot.bin file

Write your C program and compile it with a cross-compiler to generate kernel.o file.

Then use the linker to create a binary from kernel.o file which loads at 0x8000 mem location

ld -o kernel.bin -Ttext 0x8000 kernel.o --oformat binary

Concatenate both .bin files and run with VM.
cat boot.bin kernel.bin > os-image

Tell us if this works.