Чтение из памяти в реальном режиме 8086 с использованием ORG 0x0000

Я возился с сборкой x86-16 и запускал ее с VirtualBox. По какой-то причине, когда я читаю по памяти и пытаюсь напечатать ее как символ, я получаю совершенно другие результаты, чем я ожидал. Однако, когда я жестко кодирую символ как часть инструкции, он работает нормально. Вот код:

ORG 0
BITS 16

push word 0xB800        ; Address of text screen video memory in real mode for colored monitors
push cs
pop ds                  ; ds = cs
pop es                  ; es = 0xB800
jmp start

; input = di (position*2), ax (character and attributes)
putchar:
    stosw
    ret

; input = si (NUL-terminated string)
print:
    cli
    cld
    .nextChar:
        lodsb   ; mov al, [ds:si] ; si += 1
        test al, al
        jz .finish
        call putchar
        jmp .nextChar
    .finish:
        sti
        ret

start:
    mov ah, 0x0E
    mov di, 8

    ; should print P
    mov al, byte [msg]
    call putchar

    ; should print A
    mov al, byte [msg + 1]
    call putchar

    ; should print O
    mov al, byte [msg + 2]
    call putchar

    ; should print !
    mov al, byte [msg + 3]
    call putchar

    ; should print X
    mov al, 'X'
    call putchar

    ; should print Y
    mov al, 'Y'
    call putchar

    cli
    hlt

msg: db 'PAO!', 0

; Fill the rest of the bytes upto byte 510 with 0s
times 510 - ($ - $) db 0

; Header
db 0x55
db 0xAA

Печатную этикетку и инструкции в ней можно игнорировать, поскольку я еще не использовал ее из-за проблемы с печатью символа, хранящегося в памяти. Я собрал его как с FASM, так и с NASM, и у меня возникла одна и та же проблема. Это, очевидно, моя вина.

Он печатает что-то вроде:

Ответы на вопрос(1)

Ваш ответ на вопрос