Калькулятор для 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