Search code examples
assemblyx86system-callsinterruptbios

Problems with BIOS interrupt 0x10/AH=0x13 (Write String)


Working on a simple hello.s for a class, got it working with int 0x10/AH=0x0E

I would like to simplify the code with AH=0x13, which should print a string. But it doesn't work for reasons I don't understand. Code is as follows:

.code16
.global start

start:
  mov $start, %sp      # Put the stack beneath us
  call setup           # Setup BIOS modes

  xor %ax, %ax
  mov %ax, %es         # This is already zero, but let's make that clear

  mov $hello, %bp
  mov $hello_len, %cx
  call print           # Prints Hello World

  mov $hello, %bp
  mov $hello_len, %cx
  call print_string

  call done            # Halt

setup:
  mov $0x00, %ah       # Set Video mode to:
  mov $0x03, %al       # 80x25 Color Text Mode
  int $0x10            # Do it
  ret

print:                 # This routine works
  mov %bp, %si
  add %bp, %cx

  loop: cmp %si, %cx
  jz print_end

  lodsb                # Load and increment source index
  mov $0x0E, %ah       # Print single character
  int $0x10            # Do it
  jmp loop

  print_end: ret

print_string:          # This routine does not work
  mov $0x0100, %dx     # DH: Row,          DL: Column
  mov $0x1301, %ax     # AH: Write String, AL: Update Cursor
  mov $0x0007, %bx     # BH: Page Number,  BL: Color (Light Gray)

  int $0x10            # Do it
  ret

done:
  hlt

hello:
  .ascii "Hello World"
  hello_len = . - hello

.= 0x01FE
.byte 0x55, 0xAA

Code is built/run with:

as hello.s -o hello.o
ld -N -e start -Ttext=0x7c00 hello.o -o hello.elf
objcopy -O binary hello.elf hello
qemu-system-i386 -hda hello --nographic

The print routine prints "Hello World", the print_string routine moves the cursor correctly but prints no characters.

I've verified with GDB that all segment registers are zero'd, and have tried variations where I zero them explicitly. No changes. Any ideas what I'm doing wrong here? I've verified in the Seabios source that this interrupt is supported.


Solution

  • The problem is the --nographic option. Something about the nature of attribute-based output doesn't allow qemu to print strings that have attributes. But this isn't a complete answer, because the SeaBios source implies that there's effectively no difference between how these two interrupts print to the screen.