вывод lodsb на 2 разных машинах с 2 разными результатами

В настоящее время я играл с asm и низкоуровневыми вещами, такими как печать символов на экране без ОС, просто через вызовы прерывания BIOS.

мой код работает с qemu (seabios), но когда я записываю свой загрузочный сектор на usb, я получаю два разных результата на двух разных машинах

Следующий код просто вызывает прерывание BIOS (0x10), чтобы распечатать строку (соответственно символы в цикле) с функцией tty-output (0x0e).

Работает на qemu и на моем ноутбуке (вывод на экран: «12341234567»). однако, когда я использую свой настольный компьютер, вывод на экран ... ничего. Я просто получаю черный экран с мигающим знаком _ (похоже, он исходит от функции tty, и только он не печатал никаких символов)

Некоторая информация о моих системах:

Эмуляция с "qemu-system-x86_64 / dev / sdb" на моем ноутбуке

Ноутбук: Intel Atom n270 (32-бит, Phoenix Bios)

Настольный ПК: AMD Phenom II x6 1090t (64-бит, AMI Bios v1.17)

[org 0x7c00]

mov bp, 0xffff ; set stack location
mov sp, bp

mov ax, cs ; store cs in ds
mov ds, as

cld
mov si, MSG_TEST
call prnt

jmp $ ; prevent cpu from executing arbitrary bytes after this stuff aka hang

prnt:
  push ax
  push bx
  push si

  mov bh, 0
  _test_loop:
     lodsb
     cmp al, 0
     je _test_end

     mov ah, 0x0e
     int 0x10
     jmp _test_loop

_test_end:
    pop si
    pop bx
    pop ax
    ret

MSG_TEST db "12341234567", 0

times 510 - ($-$$) db 0 ; pad out (512 bytes)
dw 0xaa55 ; magic number bootable

Я не думаю, что эта проблема как-то связана с совместимостью 32/64 бит, так как на этом этапе я все еще нахожусь в 16-битном реальном режиме.


person user3469811    schedule 03.04.2015    source источник
comment
mov ds, as опечатка? должно быть mov ds, ax   -  person Alexander Zhak    schedule 03.04.2015
comment
ссылка Реализация 64-разрядной прошивки UEFI может загружать только загрузчик 64-разрядной операционной системы UEFI. или ядро. Для обратной совместимости большинство реализаций микропрограмм UEFI на компьютерах класса ПК также поддерживают загрузку в устаревшем режиме BIOS с дисков с разделами MBR через модуль поддержки совместимости (CSM), который обеспечивает совместимость с устаревшей BIOS. В этом сценарии загрузка выполняется так же, как и в устаревших системах на основе BIOS, игнорируя таблицу разделов и полагаясь на содержимое загрузочного сектора.   -  person Dirk Wolfgang Glomp    schedule 04.04.2015


Ответы (1)


Вариант 1.
Функция 0x0e требует наличия активной страницы видеорежима в регистре BH. По умолчанию это 0. mov bh, 0 перед тем, как _test_loop: должно решить проблему.
Вариант 2.
BIOS загружает загрузочный код по адресу 0x07c0: 0 вместо 0: 0x7c00. В этом случае сегменты данных и кода должны отличаться. ds: si просто указывает неверное местоположение
Вариант 3.
ПК загружается в графическом режиме, в этом случае BL должен содержать цвет символа: mov bx, 7
Вариант 4
Проблема с выравниванием стека: 0xffff - неправильное смещение. Должно быть даже. Например, 0xfffe.
Вариант 5
проблема с сегментом стека. ss тоже нужно инициализировать

Что будет, если вы попробуете

  org 0x7c00

  xor cx, cx
  mov ss, cx
  mov sp, 0x7bfe
  mov ds, cx
  mov es, cx
  mov si, text
  call print
  jmp $

print:
  ;
  ; display null-terminated ascii string in teletype mode
  ; at current cursor position
  ;
  ; input:
  ;   ds:si     - pointer to string
  ;
  mov bh, 0
  mov ah, 0x0e
  lodsb
  test al, al
  jz short $+6
  int 0x10
  jmp short $-7
  ret
person Alexander Zhak    schedule 03.04.2015
comment
это не решило проблему. У меня такие же эффекты (эмулятор / ноутбук работает, но не на ПК). Однако отредактировал свой пост с вашими предложениями, и я дополнительно помещаю bx в стек и вытаскиваю его сразу после mov bh, 0 на всякий случай - person user3469811; 03.04.2015
comment
к сожалению, я не добился успеха. option2: я изменил [org 0x7c00] на [org 0] и добавил jmp 0x7c00:bootsector_entry bootsector_entry: (если вы это имели в виду). вариант 5: я добавил mov ax, 0 и mov ss, ax - person user3469811; 03.04.2015
comment
извините, нет больше идей, банкомат. Я обычно проверяю, правильно ли входит процедура или выходит из нее, записывая символ непосредственно в видеопамять. mov ax, 0xb800 / mov es, ax / mov [es:0], byte '!' вы можете попробовать его при входе и выходе из prnt, чтобы увидеть, выполняется ли оно вообще - person Alexander Zhak; 04.04.2015
comment
Хорошо, теперь это странно: я добавил mov ax, 0xb800 / mov es, ax / mov [es:0], byte '!' между mov si, MSG_TEST и call prnt, добавил [org 0x7c00] / jmp 0x0000:bootsector_entry / bootsector_entry:, и теперь он показывает строку. Символ '!' не отображается ... Понятия не имею, почему программа так себя ведет. В любом случае спасибо за ваше время и вашу помощь. Это было очень полезно. - person user3469811; 04.04.2015
comment
попробовал код, который вы добавили в свой ответ, и он частично работает, он выводит «bdfhbdfhj», хотя я ожидал напечатать «12341234567», но похоже на проблемы с кодировкой b- ›1, d-› 2. - person user3469811; 04.04.2015