Сборка 8086 TASM - 0Ah 21h запоминает последнюю запись - PullRequest
0 голосов
/ 24 мая 2018

Итак, я пишу уникальное задание - программу, которая вычитает два введенных десятичных знака (максимум 10 символов).Первая итерация работает как задумано.Однако, когда я перезапускаю программу, почему-то вспоминается второй операнд.Приглашение ввести его появляется, но затем пропускается, как будто я уже что-то ввел - то же самое, что я ввел в первую итерацию, фактически.Вопрос в том, почему это происходит и как мне это исправить?Первая подсказка работает правильно.

Под приглашением находится INPUT_2:

    .model small             
    .386                     

    stack       100h         

    dataseg      
inputMsg1   db 0Ah, 0Dh, 'Enter first operand', 0Ah, 0Dh, '$'
inputMsg2   db 0Ah, 0Dh, 'Enter second operand', 0Ah, 0Dh, '$'
inputMax1   db 11
inputLen1   db ?
input1      db 12 dup(?)
input1Packd db 5 dup(0)
inputMax2   db 11
inputLen2   db ?
input2      db 12 dup(?)
input2Packd db 5 dup(0)
packMode    db 0            ;Режим упаковки: 1 - первая цифра, 2 - вторая
resMsg      db 0Ah, 0Dh, 'Result: $'
res         db 9 dup(' '),'$'
retryMsg    db 0Ah, 0Dh
db 'Press Any Key to continue, ESC to quit'
db '$'
errorMsg    db 0Ah, 0Dh, 'Something went wrong. Try again$'
    codeseg
START:
    startupcode

    jmp INPUT_1
INPUT_1_ERROR:
    lea DX, errorMsg
    mov AH, 09h
    int 21h
INPUT_1:
    lea DX, inputMsg1
    mov AH, 09h
    int 21h
    lea DX, inputMax1
    mov AH, 0Ah
    int 21h
    cmp inputLen1, 0
    jz  INPUT_1_ERROR
INPUT_1_PROCESS:
    lea BX, input1
    lea DX, input1Packd
    xor CX, CX
    mov CL, inputLen1
    mov SI, CX
    dec SI
    mov DI, 4
INPUT_1_LOOP:     
    mov AL, [BX][SI]
    cmp AL, '0'
    jb  INPUT_1_ERROR
    cmp AL, '9'
    ja  INPUT_1_ERROR
    and AL, 0Fh
    mov AH, packMode
    cmp AH, 0
    jnz INPUT_1_PACK_SECOND
INPUT_1_PACK_FIRST:
    inc AH
    push BX
    mov BX, DX
    mov [BX][DI], AL
    pop BX
    jmp INPUT_1_PACK_FINISHED
INPUT_1_PACK_SECOND:
    dec AH
    shl AL, 4
    push BX
    mov BX, DX
    or  [BX][DI], AL
    pop BX
    dec DI
INPUT_1_PACK_FINISHED:
    mov packMode, AH
    dec SI
    loop INPUT_1_LOOP
    mov packMode, 0
    jmp INPUT_2
INPUT_2_ERROR:
    lea DX, errorMsg
    mov AH, 09h
    int 21h
INPUT_2:
    lea DX, inputMsg2
    mov AH, 09h
    int 21h
    lea DX, inputMax2
    mov AH, 0Ah
    int 21h
    cmp inputLen2, 0
    jz  INPUT_2_ERROR
INPUT_2_PROCESS:
    lea BX, input2
    lea DX, input2Packd
    xor CX, CX
    mov CL, inputLen2
    mov SI, CX
    dec SI
    mov DI, 4
INPUT_2_LOOP:     
    mov AL, [BX][SI]
    cmp AL, '0'
    jb  INPUT_2_ERROR
    cmp AL, '9'
    ja  INPUT_2_ERROR
    and AL, 0Fh
    mov AH, packMode
    cmp AH, 0
    jnz INPUT_2_PACK_SECOND
INPUT_2_PACK_FIRST:
    inc AH
    push BX
    mov BX, DX
    mov [BX][DI], AL
    pop BX
    jmp INPUT_2_PACK_FINISHED
INPUT_2_PACK_SECOND:
    dec AH
    shl AL, 4
    push BX
    mov BX, DX
    or  [BX][DI], AL
    pop BX
    dec DI
INPUT_2_PACK_FINISHED:
    mov packMode, AH
    dec SI
    loop INPUT_2_LOOP

MATH_SETUP:
    mov SI, 4
    mov CX, 4
    mov DI, 7
MATH:
    lea BX, input1Packd
    mov AL, [BX][SI]
    lea BX, input2Packd
    mov AH, [BX][SI]
    sbb AL, AH
    pushf
    das
    dec SI
    mov AH, AL
    lea BX, res
    and AL, 0Fh
    or AL, 30h
    mov [BX][DI], AL
    dec DI
    shr AH, 4
    or AH, 30h
    mov [BX][DI], AH
    dec DI
    popf
    loop MATH


    lea BX, res
    mov CX, 7
    mov SI, 0
SHORTEN:
    mov AL, [BX][SI]
    cmp AL, '0'
    jnz WRAPUP
    inc SI
    loop SHORTEN

WRAPUP:
    push CX
    lea DX, resMsg
    mov AH, 09h
    int 21h
    lea DX, res
    pop CX
    cmp CX, 0
    jz SKIP_SHORTEN
PRINT_SHORTEN:
    add DX, 7
    sub DX, CX
    jmp FINISH_SHORTEN
SKIP_SHORTEN:
    add DX, 6
FINISH_SHORTEN:
    mov AH, 09h
    int 21h 
    lea DX, retryMsg
    mov AH, 09h
    int 21h
    mov AH, 01h
    int 21h
    cmp AL, 1Bh
    jz QUIT
    lea BX, input1Packd
    mov DX, 1
BCD_CLEANUP:
    mov DI, 0
    mov CX, 5
BCD_CLEANUP_LOOP:
    mov [BX][DI], 0
    inc DI
    loop BCD_CLEANUP_LOOP
    lea BX, input2Packd
    cmp DX, 1
    mov DX, 0
    jz BCD_CLEANUP
    jmp START
QUIT:               
    exitcode 0  

end START

Любые предложения с лучшим кодом также приветствуются, но не нужны, если у вас нет ответа на вопрос.

1 Ответ

0 голосов
/ 27 мая 2018

Буферная функция ввода DOS 0Ah позволяет вам иметь предустановленный текст в области памяти буфера ввода, который вы предоставляете.Для полного объяснения этой функции DOS см. , как работает буферизованный ввод .

Когда ваша программа впервые запускает поля inputLen1 и inputLen2 пусты из-за того, как вы определили их в источнике, используя db ?, что переводится в ноль.
Но при повторном запуске кода это уже не так!Длины все еще показывают, что вы получили в предыдущем запуске.Вам нужно обнулить оба этих поля, прежде чем снова вызывать функцию 0Ah для тех же самых входных буферов.

    mov DX, 0
    jz  BCD_CLEANUP
    mov inputLen1, DL   ;DL=0
    mov inputLen2, DL   ;DL=0
    jmp START

У цикла MATH есть пара проблем, связанных с CF.

  • Инструкция sbb al, ah зависит от значения в флаге переноса, но вы не можете убедиться, что он выключен на первой итерации этого цикла.Просто добавьте clc:

        clc
    MATH:
        lea BX, input1Packd
        mov AL, [BX][SI]
        lea BX, input2Packd
        mov AH, [BX][SI]
        sbb AL, AH
    
  • Инструкция das использует флаг переноса, который вы получаете из инструкции sbb, но это флаг переноса, который вы получаете отdas инструкция, которую необходимо сохранить / восстановить, чтобы она распространялась по циклу.

        sbb AL, AH
        das
        pushf
    

... программа, которая вычитает два введенных десятичных знака(максимум 10 символов и т. д.) ...

Если вы введете 9 или 10 символов, эти наиболее значимые цифры не будут учитываться, поскольку MATH_SETUP действительно ограничивает вас до 8 символов (что, в свою очередь, хорошо, поскольку в буфере res есть место только для отображения 8 символов)!

MATH_SETUP:
    mov SI, 4   <-- Could permit 10 packed BCD digits
    mov CX, 4   <-- Max 8 characters
    mov DI, 7   <-- Max 8 characters
...