Сборка DOS читает два следующих символа и конвертируется в число - PullRequest
1 голос
/ 29 октября 2009

Я пишу простую программу, которая принимает два числа от 1 до 99, добавляет их и распечатывает результат. Я закончил с частью печати, я могу напечатать тоже три цифры, 99 + 99 = 198, так что этого достаточно для этой программы. У меня есть программа, работающая на два однозначных числа.

Пример: 1 1 = 2, 4 4 = 8

Значит, цифры разделены пробелами. Теперь мне нужно следующее; 11 1 = 12, 1 45 = 46

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

22 будет выглядеть так: 2 2 * 10 = 20 + 2 = 22 * ​​1009 *

Обратите внимание, что остальная часть моей программы нуждается в результате этого, чтобы быть в регистре dl. Есть один крошечный вопрос о регистрах и сборке, можно ли ссылаться на число, хранящееся в dl, с помощью dx? Мне интересно, потому что mov и арифметические операторы, кажется, требуют, чтобы регистры (операнды) были одинакового размера.

Мой код пока

ReadNumber: ;; Reads one number 1-99
push ax
push bx
push cx
Lokke:
;; reads from keyboard
mov ah,01h
int 21h
cmp al, " "
je Lokke
cmp al,"0"
jb PrintError
cmp al,"9"
ja PrintError
;; First character is a valid number
push ax
;;storing the first on the stack while checking the next character
mov ah,01h
int 21h
cmp al," " 
je OneNumber
;;This part runs if the next char is a valid digit.
mov cl, al ;cl next digit
pop ax ; getting back the first from the stack
sub ax,"0" THIS LINE IS ADDED THANKS!!!!
mov bl, 10 
mul bl 
add ax, cx
mov dx,ax
mov dh,0 ;success variable set to true
mov dl,al
sub dl,"0"
pop ax
pop bx
pop cx
ret
OneNumber: 
pop ax ;; Don't need it.
mov dh,0 ;success variable set too true
mov dl,al
sub dl,"0"
pop ax
pop bx
pop cx
ret

Это не работает должным образом, даже для однозначных чисел, я не могу понять, почему :( Это выглядит просто отлично! Спасибо за ввод :)

1 Ответ

3 голосов
/ 29 октября 2009

Одна очевидная ошибка (может быть и другая) заключается в том, что вы сохраняете значение ASCII цифры, но умножаете его, как если бы оно было целым числом.

Другими словами, значение первой цифры, временно сохраненной в стеке, составляет от 48 до 57 (десятичное число), соответственно от «0» до «9».

Я проверяю другие вопросы ...

Редактировать : Второй проход ...
Я пошел дальше и предоставил эволюционную версию из вашего фрагмента , изменив несколько вещей, которые я нашел неправильными / отсутствующими, но также заложив основу для обработки более 2 цифр. Основные изменения:

  • Добавлен тест для цифры 0-9 для 2-х (и последующих) символов, считанных с ввода
  • Систематически преобразуется в целочисленное значение из ASCII, как только подтверждается достоверность цифр. (будучи последовательными, мы избегаем ошибок)
  • Использовал слово в верхней части стека для хранения кумулятивного значения (этот способ немного странный, поскольку заставляет вас выдвигать его, когда вы можете перейти / выйти. Подробнее об этом позже
  • гарантировал, что верхняя часть регистров была обнулена (это могло быть причиной некоторых ошибок)
  • Теперь у нас есть только одна точка выхода (для обычного случая, т.е. без учета «PrintError»)

Примечание: этот код не проверен, даже не скомпилирован (здесь / сейчас нет MASM) *

    ;; ReadNumber
    ;;    Reads a number from the input and returns its value in dx register
    ;;    For now 0-99 values only
    ;;      dh contains 0 = success code
    ;;      dl contains the value
    ;;    (this API should change so that bigger # can be returned)
    ReadNumber: 
    push ax
    push bx
    push cx
    Lokke:
    ;; First digit is handled separately, as to to allow for preceding spaces
    mov ah,01h
    int 21h
    cmp al, " "
    je Lokke   ;; skip spaces till first digit
    cmp al,"0"
    jb PrintError
    cmp al,"9"
    ja PrintError
    ;; First character is a valid number

    mov dh, 0
    mov dl, al
    sub dl, "0"
    push dx     ;; *** Cumulative value kept on top of stack ***

    MoreDigits:
    mov ah,01h
    int 21h
    pop cx   ;; in case of premature exit want the stack as expected...
    cmp al," "
    je DoneWithDigits
    cmp al,"0"
    jb PrintError
    cmp al,"9"
    ja PrintError
    mov dh, 0       ;; good: character is a digit
    mov dl, al
    sub dl, "0"     ;; down from ASCII
    mov ax, cx
    mov bl, 10
    mul bl
    add ax, dx    ;; fixed syntax error...
    push ax       ;; *** keep cumulative value on top of stack
    jmp DoneWithDigits  ;; For now only 2 digit max  (remove this 
                        ;; jmp to try with more)
    ;; @@@ here to test for overflow / too many char input
    jmp MoreDigits

    ;; Almost done
    DoneWithDigits: 
    pop dx 
    mov dh,0 ;success variable set too true   
    pop ax
    pop bx
    pop cx
    ret

А теперь еще несколько общих соображений

  • Заметил, что вы не используете никакие переменные в памяти (т. Е. Области памяти, которые вы определяете с помощью синтаксиса типа «MyLabel dw?» Для создания «глобальных» переменных) или даже локальные переменные (найдено при относительном смещении указателя кадра). Это может быть просто для облегчения программирования сборки и т. Д. И / или требования вашего (?) Назначения. Не спешите с обращением к таким переменным, но они вам пригодятся, когда вы это сделаете.
  • Соглашение о вызовах : кажется, что методы ReadNumber () отвечают за защиту регистров ax, bx и cx. (и восстановить их перед выходом). Это немного странное соглашение, обычно вызывающий метод помещает свой собственный контекст в стек (а затем помещает любой параметр в функцию, если таковой имеется). В любом случае вы увидите эти соглашения в действии, а также способ использования регистра указателя кадра (BP) и т. Д. Может быть, вы можете проверить эту статью в Википедии в качестве предварительного просмотра (кстати, в зависимости от того, какой ассемблер вы используете если это макро-ассемблер, вы можете позаботиться об этой механике.) Не спешите делать все это, сначала ознакомьтесь с основами сборки.
  • макет кода немного странный, при сборке нам обычно нравится макет из 4 столбцов с метками в первом столбце, красивым и видимым, затем инструкции, затем операнды и последние комментарии строки.

Надеюсь, это поможет,
повеселись!

...