Калькулятор для 2/8/10/16-ричных систем счисления

Имеется код для выполнения арифметических действий в двоичной и шестнадцатеричной системах счисления. Я пытался по аналогии добавить восьмеричную систему счисления, но явно сделал неправильно, так как, например, сложение осуществляется неверным образом (например, 1+7=0008, хотя 8 не должна присутствовать вообще)

.model tiny
 
.code
 
        org     100h
main    proc
 
        jmp     start
 
        OpMul           equ     '*'
        OpDiv           equ     '/'
        OpAdd           equ     '+'
        OpSub           equ     '-'
        ;Данные
        BinChars        db      '01'
        LenBinChars     dw      $-BinChars
        HexChars        db      '0123456789ABCDEFabcdef'
        LenHexChars     dw      $-HexChars
        OpChars         db      '=+-*/'
        LenOpChars      dw      $-OpChars
        CrLf            db      0Dh, 0Ah, '$'
        msgPromptBase   db      'Select the base (bin/hex)? (b/h) ', '$'
        msgPromptExpr   db      0Dh, 0Ah, 'Expression: ', '$'
        msgResult       db      'Result: ', '$'
        msgPressAnyKey  db      0Dh, 0Ah, 'Press any key to exit...', '$'
        BaseChars       dw      ?
        BaseCharsLen    dw      ?
        Base            dw      ?
        FirstNumb       dw      ?
        SecondNumb      dw      ?
        Operation       db      ?
        CurrChar        db      ?
        kbdBuf          db      80, 81 dup(?)
start:
        ;программа
        ;ввод основания счисления
        mov     ah,     09h
        lea     dx,     [msgPromptBase]
        int     21h
        @@GetBase:
                mov     ah,     00h
                int     16h
                cmp     al,     'b'
                je      @@StoreBase
                cmp     al,     'h'
                je      @@StoreBase
                jmp     @@GetBase
        @@StoreBase:
        int     29h
        lea     bx,     [BinChars]
        mov     [BaseChars],    bx
        mov     bx,     [LenBinChars]
        mov     [BaseCharsLen], bx
        mov     [Base], 2
        cmp     al,     'b'
        je      @@Base
        lea     bx,     [HexChars]
        mov     [BaseChars],    bx
        mov     bx,     [LenHexChars]
        mov     [BaseCharsLen], bx
        mov     [Base], 16
        @@Base:
        ;ввод чисел и операций
        mov     ah,     09h
        lea     dx,     [msgPromptExpr]
        int     21h
 
        mov     [FirstNumb],    0
        mov     [SecondNumb],   0
        mov     [Operation],    OpAdd
        @@GetCmd:
                mov     ah,     00h
                int     16h
                mov     [CurrChar],     al
                ;проверка корректности введённых символов
                lea     di,     [OpChars]
                mov     cx,     [LenOpChars]
                repne   scasb
                jnz     @@TestDigits
                int     29h
                jmp     @@DoOperation
        @@TestDigits:
                mov     di,     [BaseChars]
                mov     cx,     [BaseCharsLen]
                repne   scasb
                jnz     @@GetCmd
                int     29h
                ;введена цифра
                sub     al,     '0'
                cmp     al,     9
                jbe     @@DoDigit
                sub     al,     'A'-'0'+10
                cmp     al,     15
                jbe     @@DoDigit
                sub     al,     'a'-'A'
        @@DoDigit:
                mov     bx,     0
                mov     bl,     al
                mov     ax,     [SecondNumb]
                mul     [Base]
                add     ax,     bx
                mov     [SecondNumb],   ax
                jmp     @@GetCmd
 
        @@DoOperation:
                ;сначала завершается предыдущая операция
                mov     ax,     [FirstNumb]
                mov     dx,     0
                mov     bx,     [SecondNumb]
                cmp     [Operation],    '+'
                jne     @@Sub
                add     ax,     bx
                jmp     @@Calc
        @@Sub:
                cmp     [Operation],    '-'
                jne     @@Mul
                sub     ax,     bx
                jmp     @@Calc
        @@Mul:
                cmp     [Operation],    '*'
                jne     @@Div
                mul     bx
        @@Div:
                cmp     [Operation],    '/'
                jne     @@Calc
                div     bx
        @@Calc:
                mov     [FirstNumb],    ax
                mov     [SecondNumb],   0
                mov     al,     [CurrChar]
                mov     [Operation],    al
                cmp     al,     '='
                je      @@Break
        jmp     @@GetCmd
@@Break:
        mov     ax,     [FirstNumb]
        cmp     [Base], 2
        jne     @@ShowResHex
        call    ShowBin
        jmp     @@NewLine
        @@ShowResHex:
        call    ShowHex
        @@NewLine:
        mov     ah,     09h
        lea     dx,     [msgPressAnyKey]
        int     21h
 
        mov     ah,     00h
        int     16h
 
        int     20h
main    endp
 
;выводит на экран в 16 системе счисления содержимое регистра AX
; входные данные:
; ax - число для отображения
ShowHex proc
        push    ax
        push    cx
        push    dx
 
        ; Начинаем перевод числа AX в строку
        mov    cl,      ((16-1)/4)*4    ; 16-битный регистр, будем выводить по 4 бита (0..F)
        xchg   dx,      ax              ; Сохраняем число в DX
 
@@Repeat:
 
        mov    ax,      dx              ; Восстанавливаем число в AX
        shr    ax,      cl              ; Сдвигаем на CL бит вправо
        and    al,      0Fh             ; Получаем в AL цифру 0..15
        add    al,      '0'             ; Получаем в AL символ цифры
        cmp    al,      '9'             ; Проверяем цифру
        jbe    @@Digit09                ; Прыгаем, если это цифра 0..9
        add    al,      'A'-('9'+1)     ; Иначе (для A..F) корректируем ее
 
@@Digit09:
 
        int    29h                      ; Выводим символ в AL на экран
        sub    cl,      4               ; Уменьшаем CL на 4 для следующей цифры
        jnc    @@Repeat                 ; Если знаковый CL >= 0, то повторяем
 
        pop     dx
        pop     cx
        pop     ax
        ret
ShowHex endp
 
;выводит на экран в двоичной системе счисления содержимое регистра AX
; входные данные:
; ax - число для отображения
ShowBin proc
        push    ax
        push    bx
        push    cx
 
        mov     bx,     ax      ; из-за распределения регистров
                                ; при выводе на экран с помощью int 29h,
                                ; выводимое число будет находится в bx
        mov     cx,     16      ; переменная цикла равна количеству бит в слове
 
@@For:
 
        mov     ax,     '0'     ; в регистрах al=код символа '0', ah=00h
 
        shl     bx,     1       ; выделение бита
 
        adc     al,     ah      ; сложение кода символа '0' со значением выделенного бита
 
        int     29h
 
        loop    @@For
 
        pop     cx
        pop     bx
        pop     ax
        ret
ShowBin endp
 
end     main

Ответы (1 шт):

Автор решения: LShadow77

Я это, естественно, не отлаживал, но попробуй так:

    ;выводит на экран в восьмиричной системе счисления содержимое регистра AX
    ; входные данные:
    ; ax - число для отображения

ShowOct proc
        push    ax
        push    cx
        push    dx

        mov    dx,      ax              ; Сохраняем число в DX
        mov    cx,      6               ; в CX - число разрядов

        получаем старший разряд (бит 15)
        rol    dx,      1               ;сдвигаем старший в младший
        mov    al,      dl
        and    al,      1
        jmp    short @@ToChar

        ;выводим остальные 15 бит - 5 восьмиричных разрядов по 3 бита в каждом
@@Repeat:
 
        rol    dx,      3               ; сдвигаем старшие в младшие
        mov    al,      dl
        and    al,      7               ; Получаем в AL цифру 0..7
@@ToChar:
        or     al,      30h             ; Получаем в AL символ цифры
        int    29h                      ; Выводим символ в AL на экран
        loop   @@Repeat                 ; повторяем
 
        pop     dx
        pop     cx
        pop     ax
        ret
ShowOct endp
→ Ссылка