; TASM Вычислить Выражение (переменные вводятся с клавиатуры) a*c*(a+b)-d
; a, b, c – define byte, d – define word
.model small
.code
a db 0
b db 0
c db 0
d dw 0
res dw 0
start: mov ax,cs
mov ds,ax
mov es,ax
call pthis
db "'a*c*(a+b)-d' calculator",13,10,0
call pthis
db 13,10,"byte a=",0
call scan_byte
mov a,cl
call pthis
db 13,10,"byte b=",0
call scan_byte
mov b,cl
call pthis
db 13,10,"byte c=",0
call scan_byte
mov c,cl
call pthis
db 13,10,"word d=",0
call scan_num
mov d,cx
mov al,a
mov bl,b
mov ah,0
mov bh,0
add ax,bx
cmp ah,0
jnz over1
mov ah,c
mul ah ; ax=c*(a+b)
mov cx,ax
mov al,a
mov ah,0
mul cx ; ax=a*c*(a+b)
cmp dx,0
jnz over1
sub ax,d ; ax=a*c*(a+b)-d
mov res,ax
call pthis
db 13,10,"result=",0
mov ax,res
call print_num
int 20h ; выход в Дос
over1: call pthis
db "Number is out of bounds",0
int 20h ; выход в Дос
scan_byte:call scan_num ; ввести число
cmp ch,0 ; число не умещается в байт ?
jnz over1
ret ; иначе возврат
;****************************
; include io86.inc
; ***************************
; Подпрограммы ввода и вывода
; ***************************
; this macro prints a char in AL and advances
; the current cursor position:
; макро - вывод символа char на дисплей
PUTC MACRO char
PUSH AX
push dx
MOV DL, char
MOV AH, 2
INT 21h
pop dx
POP AX
ENDM
;
; CALL PTHIS
; db 'Hello World!', 0
;
PTHIS:
MOV CS:temp1, SI ; store SI register.
POP SI ; get return address (IP).
PUSH AX ; store AX register.
next_char:
MOV AL, CS:[SI]
INC SI ; next byte.
CMP AL, 0
JZ printed
MOV AH, 0Eh ; teletype function.
INT 10h
JMP next_char ; loop.
printed:
POP AX ; re-store AX register.
; SI should point to next command after
; the CALL instruction and string definition:
PUSH SI ; save new return address into the Stack.
MOV SI, CS:temp1 ; re-store SI register.
RET
temp1 DW ? ; variable to store original value of SI register.
; ввод числа CX со знаком
SCAN_NUM:
PUSH DX
PUSH AX
PUSH SI
MOV CX, 0 ; начальное значение cx=0
; reset flag:
MOV CS:make_minus, 0
next_digit: ; начало цикла ввода
; get char from keyboard
; into AL:
MOV AH, 00h ; ввести символ AL с клавиатуры...
INT 16h
; and print it:
MOV AH, 0Eh ; ... и напечатать его
INT 10h
; check for MINUS:
CMP AL, '-' ; проверить ввод знака минус
JE set_minus
; check for ENTER key:
CMP AL, 13 ; carriage return? ; если enter то выход из подпрограммы
JNE not_cr
JMP stop_input
not_cr:
CMP AL, 8 ; 'BACKSPACE' pressed? - забой - убрать последнюю цифру
JNE backspace_checked
MOV DX, 0 ; remove last digit by
MOV AX, CX ; division:
DIV CS:ten ; AX = DX:AX / 10 (DX-rem).
MOV CX, AX
PUTC ' ' ; clear position. ; стереть последнюю цифру с дисплея
PUTC 8 ; backspace again.
JMP next_digit
backspace_checked:
; allow only digits:
CMP AL, '0' ; это цифра ?
JAE ok_AE_0
JMP remove_not_digit
ok_AE_0:
CMP AL, '9'
JBE ok_digit
remove_not_digit:
PUTC 8 ; backspace. ; это не цифра - стереть символ
PUTC ' ' ; clear last entered not digit.
PUTC 8 ; backspace again.
JMP next_digit ; wait for next input.
ok_digit: ; да, это цифра
; multiply CX by 10 (first time the result is zero) ; умножить cx на 10
PUSH AX
MOV AX, CX
MUL CS:ten ; DX:AX = AX*10
MOV CX, AX
POP AX
; check if the number is too big
; (result should be 16 bits)
CMP DX, 0 ; если число не влезает в 16 бит, то переход на too_big
JNE too_big
; convert from ASCII code:
SUB AL, 30h ; преобразовать код символа в цифру
; add AL to CX: ; CX=CX+AX
MOV AH, 0
MOV DX, CX ; backup, in case the result will be too big.
ADD CX, AX
JC too_big2 ; jump if the number is too big.
JMP next_digit
set_minus:
MOV CS:make_minus, 1
JMP next_digit
too_big2: ; отмена, если число слишком большое вариант 2
MOV CX, DX ; restore the backuped value before add.
MOV DX, 0 ; DX was zero before backup!
too_big: ; отмена, если число слишком большое
MOV AX, CX
DIV CS:ten ; reverse last DX:AX = AX*10, make AX = DX:AX / 10
MOV CX, AX
PUTC 8 ; backspace. ; затереть последнюю цифру
PUTC ' ' ; clear last entered digit.
PUTC 8 ; backspace again.
JMP next_digit ; wait for Enter/Backspace. ; переход к началу цикла ввода
stop_input: ; если был введен минус, то изменить знак CX
; check flag:
CMP CS:make_minus, 0
JE not_minus
NEG CX
not_minus: ; всё сделано - выход из подпрограммы
POP SI
POP AX
POP DX
RET
make_minus DB ? ; used as a flag. флаг "был введён минус"
; печать числа AX со знаком
PRINT_NUM:
PUSH DX
PUSH AX
CMP AX, 0
JNZ not_zero
PUTC '0' ; если число=0 то просто напечатать "0" и выйти
JMP printed2
not_zero:
; the check SIGN of AX,
; make absolute if it's negative:
CMP AX, 0
JNS positive
NEG AX ; если число отрицательное, то напечатать минус и изменить знак числа
PUTC '-'
positive:
CALL PRINT_NUM_UNS ; вызвать подпрограмму "печать числа без знака"
printed2:
POP AX
POP DX
RET ; выход
; печать числа AX без знака
PRINT_NUM_UNS:
PUSH AX
PUSH BX
PUSH CX
PUSH DX
; flag to prevent printing zeros before number:
MOV CX, 1 ; флаг "не печатать нули перед числом"
; (result of "/ 10000" is always less or equal to 9).
MOV BX, 10000 ; 2710h - divider. ; делитель=10000
; AX is zero?
CMP AX, 0
JZ print_zero
begin_print:
; check divider (if zero go to end_print):
CMP BX,0 ; если bx=0 то закончить печать
JZ end_print
; avoid printing zeros before number:
CMP CX, 0 ; не печатать лидирующие нули
JE calc
; if AX<BX then result of DIV will be zero:
CMP AX, BX ; если AX<BX то результат деления=0
JB skip
calc:
MOV CX, 0 ; set flag.
MOV DX, 0
DIV BX ; AX = DX:AX / BX (DX=remainder).
; print last digit
; AH is always ZERO, so it's ignored
ADD AL, 30h ; convert to ASCII code.
PUTC AL ; напечатать очередную цифру
MOV AX, DX ; get remainder from last div. ; AX=остаток от последнего деления
skip:
; calculate вычислить BX=BX/10
PUSH AX
MOV DX, 0
MOV AX, BX
DIV CS:ten ; AX = DX:AX / 10 (DX=remainder).
MOV BX, AX
POP AX
JMP begin_print ; переход к началу цикла
print_zero:
PUTC '0' ; напечатать "0"
end_print: ; выход из подпрограммы
POP DX
POP CX
POP BX
POP AX
RET
ten DW 10 ; used as divider. ; константа делитель
end start
Мне сказали,что он вышел у меня слишком огромным и такой код можно написать проще.Помогите,пожалуйста как-то это по-красивому исправить,чтобы код выглядел опрятно