0

Here is my new kernel code that should print a(btw the reason it's called printstack is because I'm trying to pass parameters by stack, but that didn't work):

void printstack(char in){ /*print function*/
       asm ("mov ah,0x0e\n"
         "mov al,%0\n"
         "int 0x10\n"
    ::"r"(in)
    ); 
}
void main(){ /*kernel entry point*/
  printstack('a');
}

However when I test it in QEMU, it only print spaces.

Here is the full script that build os.flp:

 echo ">>> Creating floppy image..."
   mkdosfs -C os.flp 1440 || exit   
    echo ">>> Assembling bootloader..."

    nasm -O0 -w+orphan-labels -f bin -o source/bootload/bootload.bin source/bootload/bootload.asm || exit

    echo "compiling kernel"
    gcc -c ./source/kernel.c -masm=intel 
    ld --oformat binary kernel.o -o ./source/kernel.bin  -e main



    echo ">>> Adding bootloader to floppy image..."

    dd status=noxfer conv=notrunc if=source/bootload/bootload.bin   of=os.flp || exit


    echo ">>> Copying kernel"

    rm -rf tmp-loop

    mkdir tmp-loop && mount -o loop -t vfat os.flp tmp-loop && cp source/kernel.bin tmp-loop/


    sleep 0.2

    echo ">>> Unmounting loopback floppy..."

    umount tmp-loop || exit

    rm -rf tmp-loop


t

    echo '>>> Done!'
Clement Poon
  • 79
  • 1
  • 6
  • Please post a [Minimal, Reproducible Example](https://stackoverflow.com/help/minimal-reproducible-example). How is `os.flp` built? Is the entry point taken into account correctly? – MikeCAT May 09 '20 at 10:42
  • This should depend on the environment, but moving the definition of `main()` before one of `printstack` may have it behave better. (declaretion of `printstack` should be before `main()` then) – MikeCAT May 09 '20 at 10:44
  • 1
    Your constraints don't describe the fact that it modifies EAX (by overwriting AH). That seems unlikely to be the problem with that as your only C, especially for 64-bit code. Oh, but you don't have any asm to call your C! You're making 64-bit machine code and then executing it in 16-bit real mode via QEMU. The REX prefixes on `push rbp` / `mov rbp,rsp` will decode as `dec eax` instructions... Single-step the asm in a debugger to see what happened. Also, the compiler's `ret` at the end of the function might be causing havoc. Write an infinite loop and compile with `gcc -m16`. – Peter Cordes May 09 '20 at 11:54
  • Using GCC to generate code to run in 16-bit real mode is fraught with problems (I don't recommend it). If you choose to do this despite the warning you will need to use `-m16` GCC option; before loading your kernel SS=DS=CS=ES=0 (and set SP stack pointer) prior to calling `main`; compile using `-ffreestanding`. There is an answer (under the section _Proper use of Inline Assembly to Write a String Using the BIOS_) that gives an example of building a kernel and using inline assembly targeting real mode https://stackoverflow.com/a/57932741/3857942 – Michael Petch May 09 '20 at 13:37

1 Answers1

-1

I somehow solved it by switching the position of main and printstack:

void main(){
  printstack('a');
}

void printstack(char in){
       asm volatile("mov ah,0x0e\n"
         "mov al,%0\n"
         "int 0x10\n"
    ::"r"(in)
    :"eax"
    ); 
}
Clement Poon
  • 79
  • 1
  • 6
  • 1
    If that makes a difference, something is seriously broken and you can't count on more complicated C working as expected. Also, you're still missing a clobber declaration on `"eax"`. – Peter Cordes May 09 '20 at 12:49