После команды JMP программа не возвращается в то место, где она была вызвана - PullRequest
1 голос
/ 12 апреля 2019

Я пытаюсь написать простой графический движок для DOSBOX, и он идет довольно хорошо, я использую некоторый код из https://github.com/adamsmasher/sokobanDOS/
Моя проблема в том, что после того, как я вызываю команду JMP для перехода к drawpixel, программа не возвращается в main, по крайней мере, я так не думаю. После drawpixel он должен вернуться к тексту, который я тестировал самостоятельно, и он работает.
Я новичок в сборке, поэтому я не знаю, что делаю.

jmp initgraph

main:
    MOV CX, 320
    JMP drawpixel
    JMP returntext
    JMP main

initgraph:
    MOV AX, 13h
    INT 10h
    MOV CX, 0
    JMP main

returntext:
    MOV AX, 0x03
    INT 0x10
    RET

drawpixel:
    MOV AX, 0A000h
    MOV ES, AX
    MOV AX, CX
    MOV DI, AX
    MOV DL, 0xE
    MOV [ES:DI], DL

Он должен просто очень быстро отображать пиксель и возвращаться в текстовый режим, но вместо этого он как бы зависает и не возвращается к тексту.

1 Ответ

2 голосов
/ 12 апреля 2019

Проблема в том, что вы используете JMP вместо CALL.

Когда вы используете JMP (или любое из его условных отклонений), вы инструктируете ЦПУ заменить текущий указатель инструкциис непосредственным или вычисленным значением, закодированным с операндом.Не предусмотрено отслеживание того, где вы были.

Когда вы используете операцию CALL, адрес следующего кода операции помещается в стек, SP уменьшается на соответствующую ширину стека,и немедленное / вычисленное значение в вызове помещается в указатель инструкции.Это позволяет использовать инструкцию RET для возврата к предыдущему месту выполнения.

Пример кода, который использует CALL, входит в графический режим, строит пиксель, ждет клавишу, возвращается в текстовый режим итогда выход обратно в DOS может выглядеть так:

org 100h

main:
    CALL initgraph
    MOV CX, 320
    CALL drawpixel
    CALL waitforkey
    CALL returntext

    MOV AX, 4C00h               ; Exit to DOS returning exit code 00h
    INT 21h

waitforkey:
    MOV AH, 0                   ; Int 16h/AH=0 get key BIOS call
    INT 16h
    RET

initgraph:
    MOV AX, 13h
    INT 10h
    MOV CX, 0
    RET

returntext:
    MOV AX, 0x03
    INT 0x10
    RET

drawpixel:
    MOV AX, 0A000h
    MOV ES, AX
    MOV AX, CX
    MOV DI, AX
    MOV DL, 0xE
    MOV [ES:DI], DL
    RET
...