INT 10h не печатает символ, переданный через стек - PullRequest
0 голосов
/ 12 сентября 2018

Я следую инструкциям в книге. Я пытаюсь написать простой загрузчик на i8086 на QEMU.
Я использую прерывание BIOS (INT 10, E - Запись текста в режиме телетайпа), чтобы распечатать символ в позиции, которую я установил до этого, также с прерыванием BIOS (INT 10,2 - Установить положение курсора).

Настройка положения курсора работает.

Моя цель - создать подпрограмму "PutChar", которая принимает в качестве параметра символ и затем печатает его. Печать char напрямую (т.е. mov al, 'c') работает нормально, что показывает, что он действительно будет работать.

Регистр AL принимает символ для печати. ​​
Регистр AH определяет, какую функцию следует выполнять с INT 10h.

Я поставил звезду, где фактический параметр должен быть скопирован в AH .

Однако где-то я совершаю ошибку, которую не могу найти. Я вычислял снова и снова, правильно ли я сослался на 'A' в стеке, я даже пытался [bp], [bp + 8] и [bp + 16] просто из отчаяния, так сказать.

Запуск этих результатов приводит к тому, что ничего не печатается, даже «странный» символ ASCII, что приводит меня к мысли, что в указанном адресе ничего нет. Очевидно, я где-то ошибаюсь, но где?

следующий код:

;********************
;A simple bootloader
;*******************
org 0x7c00
bits 16

start: 
  call MoveCursor
  push 'A' ; SP--, then put 'A' on stack. (8 bit only)
  call PutChar
  jmp boot


MoveCursor:
  mov bh, 0
  mov dh, 11
  mov dl, 10
  mov ah, 02h
  int 10h
  ret

PutChar:
  push bp ; SP--, SP--, then put Base Pointer on stack (16 bit)
  mov  bp, sp ;Copy Stack Pointer to Base Pointer
  *mov al, [bp+16] ;Since [bp] points to the old Base Pointer and the Base Pointer is 16 bits long, going back 16 bit would result in 'A', right?
  mov ah, 0eh
  int 10h
  pop bp 
  ret


boot:
  cli ;no interrupt
  cld ;all that we need to init
  hlt ;halt the system

;We have to be 512 bytes. Clear the rest of the bytes with 0
times 510 - ($-$$) db 0
dw 0xAA55

1 Ответ

0 голосов
/ 12 сентября 2018

Благодаря @ Маргарет Блум я решил это.Я на самом деле сделал просчет, и я также не учел, что [bp+8] на самом деле означает 8 байт после bp вместо бит , как я изначальнотолько предположил.Думая теперь, байты просто логичны - ошибка с моей стороны.

Тогда я забыл, что вызов функции также добавляет в стек: адрес возврата, конечно.

Итак, в следующем порядкезначения помещаются в стек:

  1. 'A' (8 бит, но так как вы не можете вставить 8 бит на x86, 16 бит будут выталкиваться в формате с прямым порядком байтов)
  2. currentIP (16 бит)
  3. BP (16 бит) (<- SP здесь и сейчас) </li>

Затем я сохраняю SP в BP и использую BP, чтобы обратиться к моему параметру 'A».Поскольку [BP] является моим SP, [BP + 2] будет моим обратным адресом, и, наконец, [BP + 4] является моим параметром.

Обратите внимание, как я уже сказал, +2 означает 2 байта, а не бит.

...