asm("mov $0x0, %%ax;int $0x16;mov %%al, %0" : "=r" (al) : );
"Error: Suffix or Operands invalid for 'mov' "
Das Problem ist, dass die Operandengrößen nicht passen. al ist ein int, deswegen wird %0 zu z.B. edx, nicht zu dl. Du kannst entweder aus al einen char machen oder %b0 verwenden, wodurch nur das niederwertigste Byte benutzt wird.
In Wirklichkeit willst du das ganze aber sowieso ganz anders schreiben, du kannst nämlich dem Compiler gleich sagen, dass er eax benutzen soll:
asm("int $0x16" : "=a" (al) : "0" (0x0));
Die BIOS-Interrupts zu benutzen ist nicht so furchtbar hilfreich. Das Problem dabei ist, dass das BIOS die Interrupthandler in 16-Bit-Real-Mode-Code implementiert. Dir bleibt also nur, entweder in den Real Mode zurückzuschalten oder den BIOS-Code im VM86 laufen zu lassen, wenn die du BIOS-Interrupts benutzen willst. In der Regel macht man das nur, um in die VESA-Grafikmodi schalten zu können und lässt das BIOS ansonsten in Ruhe.