Печатать числа по диагонали в сборке

Я пытаюсь отобразить 0-9 по диагонали в ассемблере, но на выходе мои числа, напечатанные по диагонали, помещаются в середину окна.

Вот код:

start:
mov ah, 02h 
mov cl, 0Ah ;counter (10)
mov dx, 02h
;mov bx, 02h
mov dl, 30h ;start printing 0-9
mov dh, 02h ;start row
mov al, 02h
int 21h

again:

int 10h
int 21h
;add dx, 01h
inc dh
inc dx
inc al

loop again
mov ax, 4c00h
int 21h

Вывод должен быть:

0
  1
    2
      3
        4
          5
            6
              7
                8 
                  9

Текущий вывод печатает это, но в середине окна. Я попытался добавить новый регистр bh и использовать его, чтобы поместить курсор в мою текущую позицию при выполнении файла. Как я могу отобразить его, начиная с моего курсора? Должен ли я поставить его на цикл и увеличить регистр ah?


person Kirk    schedule 20.11.2017    source источник
comment
сначала напечатайте возврат каретки и новую строку (CR + LF, ascii 10 и 13), это переместит курсор в первую позицию следующей строки   -  person Tommylee2k    schedule 20.11.2017
comment
это или если есть вариант приготовленный против сырого. в мире pc/dos приготовленный означает, что 0x0A превращается в 0x0D 0x0A, в противном случае вам придется делать это самостоятельно, что я предполагаю для этого системного вызова, вам нужно будет сделать это самостоятельно.   -  person old_timer    schedule 20.11.2017


Ответы (1)


Ваша текущая программа дает сбой, потому что вы ужасно смешиваете 2 системные функции, которые имеют один и тот же номер функции 02h, но ожидают получить совершенно разные данные в регистре DL. Функция DOS OutputCharacter ожидает код символа, и вы устанавливаете его равным 48, но функция BIOS SetCursor будет интерпретировать то же значение 48, что и столбец. Именно поэтому результаты отображаются посередине экрана!

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

    mov     ah, 02h
    mov     dl, "0"
Next:
    push    dx          ;Preserve current character
    int     21h
    mov     dl, " "     ;Your desired output shows this space?
    int     21h
    mov     dl, 10      ;Linefeed moves the cursor 1 line down
    int     21h
    pop     dx          ;Restore current character
    inc     dl
    cmp     dl, "9"
    jbe     Next

Вместо того, чтобы использовать отдельный счетчик, вы можете принять решение о зацикливании, просмотрев значение в увеличенном регистре DL.


Обратите внимание, что вы использовали инструкцию loop, которая зависит от регистра CX, но вы инициализировали только его нижнюю половину CL! Это часто является причиной сбоя программы.


ИЗМЕНИТЬ

Учитывая, что DOSBox выдает как возврат каретки, так и перевод строки, когда его просят отобразить символ 10 (доведено до моего сведения в этот комментарий Майкла Петча), я написал следующую маленькую программу, которую проверил на точность в последней доступной версии DOSBox 0.74.

    ORG     256          ;Create .COM program

    mov     ah, 02h      ;DOS.DisplayCharacter
    mov     dx, "0"      ;DH is spaces counter, DL is current character
    jmps    First        ;Character "0" has no prepended spaces!
Next:
    push    dx           ;(1)
    mov     dl, " "
Spaces:
    int     21h
    dec     dh
    jnz     Spaces
    pop     dx           ;(1)
First:
    int     21h          ;Display character in DL
    push    dx           ;(2)
    mov     dl, 10       ;Only on DOSBox does this do Carriage return AND Linefeed !
    int     21h
    pop     dx           ;(2)
    add     dx, 0201h    ;SIMD : DH+2 and DL+1
    cmp     dl, "9"
    jbe     Next

    mov     ax, 4C00h    ;DOS.TerminateWithExitcode
    int     21h
person Sep Roland    schedule 26.11.2017
comment
Вопрос был помечен как DOSBox. Любопытно, проверяли ли вы его в этой среде (используя стандартный эмулятор DOSBox)? Насколько я знаю, и неисправленный DOSBox будет печатать перевод строки как CRLF (очевидно, недостаток по дизайну), поэтому этот ответ не будет печатать его по диагонали. Ваш код, конечно же, будет работать при запуске реальной версии DOS (даже в DOSBox). - person Michael Petch; 08.12.2017
comment
@MichaelPetch Ты прав. Я только что проверил это сам и обнаружил, что 10, по-видимому, означает 13 + 10 для DOSBox. Я добавил новое решение и проверил его на этот раз! - person Sep Roland; 10.12.2017