Здравствуйте, m1dvet!
Ошибка характерная для всех новичков в ассемблере.
-
Установка начального значения регистров.Изменяем Ваш код, добавляем контроль регистра с вводимым числом:
[code lang=asm h=350]ORG 100h
MOV AH, 09h
MOV DX, TXT1
INT 21h
MOV BX, 3E8h
CALL WRITE_DEC
MUL BX
ADD BP, AX
mov ax,bp
call outnum
MOV BX, 64h
CALL WRITE_DEC
MUL BX
ADD BP, AX
MOV BX, 0Ah
CALL WRITE_DEC
MUL BX
ADD BP, AX
CALL WRITE_DEC
ADD BP, AX
MOV AH, 09h
MOV DX, TXT2
INT 21h
MOV BX, 3E8h
CALL WRITE_DEC
MUL BX
ADD DI, AX
mov ax,di
call outnum
MOV BX, 64h
CALL WRITE_DEC
MUL BX
ADD DI, AX
MOV BX, 0Ah
CALL WRITE_DEC
MUL BX
ADD DI, AX
CALL WRITE_DEC
ADD DI, AX
MOV AX, BP
MOV BX, DI
MOV CX, 0000h
MOV DX, 0000h
DIV BX
MOV BX, DX
PUSH BX
PUSH AX
MOV AH, 09h
MOV DX, TXT3
INT 21h
POP AX
CALL T_DEC
MOV AH, 09h
MOV DX, TXT4
INT 21h
POP BX
MOV AX, BX
CALL T_DEC
NOP
xor ax,ax
int 16h
INT 20h
WRITE_DEC:
NEW: MOV AH, 08h; ФУНКЦИЯ ВВОДА СИМВОЛА C'ЭХА'
INT 21h; ВSВОД СИМВОЛА
MOV DL, AL
CMP AL, 30h; ДЛЯ УСТАНОВКИ ФЛАГА, СРАВНИВАЕМ 30 И AL
JB FLAG_ON; ЕСЛИ МЕНЬШЕ, ФЛАГ УСТАНОВЛЕН (CF=1), ТО ПЕРЕХОДИМ К МЕТКЕ FLAG_ON
CMP AL, 39h; СРАВНИВАЕМ 39 И AL
JA FLAG_ON; ЕСЛИ AL > 39 ФЛАГ УСТАНОВЛЕН (CF=1), ТО ПЕРЕХОДИМ К МЕТКЕ FLAG_ON
CLC
JMP A1
FLAG_ON:STC; УСТАНАВЛИВАЕМ ФЛАГ (CF=1)
A1: JC NEW; ЕСЛИ ФЛАГ УСТАНОВЛЕН, ТО ПЕРЕХОД К МЕТКЕ NEW
MOV AH, 02h; ВЫВОД DL
INT 21h; НА ЭКРАН
SUB AL, 30h; ИЗ СОДЕРЖИМОГО AL ОТНИМАЕМ 30h
XOR AH,AH
RET
T_DEC:
MOV CX,0000h; ОБНУЛЯЕМ CX
MOV BX,0Ah; ДЕЛИТЕЛЬ - 10
ZERO_DX:MOV DX,0000h; ОБНУЛЯЕМ DX (ДЛЯ ОСТАТКА)
DIV BX; ДЕЛЕНИЕ: ЧАСТНОЕ В AX, ОСТАТОК В DX
PUSH DX; ЗАПИСЬ ОСТАТКА В СТЕК ДЛЯ ПОСЛЕДУЮЩЕГО ВЫВОДА
INC CX; УВЕЛИЧИТЬ СЧЕТЧИК НА 1
OR AX,AX; ПРОВЕРКА НА 0
JNZ ZERO_DX; ЕСЛИ НЕ 0, ПОВТОРЯЕМ ДЕЛЕНИЕ
FROM_STEK:
POP DX; ИЗВЛЕКАЕМ ОСТАТОК
ADD DL, 30h; ПОЛУЧАЕМ ASCII-символ
MOV AH, 02h; ВЫВОД СИМВОЛА
INT 21h; НА ЭКРАН
DEC CX; УМЕНЬШАЕМ СЧЕТЧИК НА 1
OR CX, CX; СРАВНИВАЕМ С 0
JNZ FROM_STEK; ЕСЛИ НЕ 0, ИЗВЛЕКАЕМ СЛЕДУЮЩИЙ ОСТАТОК
RET; ВОЗВРАТ ИЗ ПРОЦЕДУРЫ
outnum: pusha
xor cx,cx
mov bx,10
@@01: xor dx,dx
div bx
push dx
inc cx
or ax,ax
jnz @@01
mov al,'('
int 29h
@@02: pop ax
or al,'0'
int 29h
loop @@02
mov al,')'
int 29h
popa
ret
TXT1 DB 'xxxx / yyyy:=$'
TXT2 DB ' / $'
TXT3 DB ' ax= $'
TXT4 DB 13,10,' dx = $'[/code]
Получаем картинку(в скобках значение регистра):
Теперь - почему, это происходит. Пишем такой код:
[code lang=asm]org 100h
call @@00
mov ah,9
mov dx,dbMess
int 21h
@@00: pusha
mov cx,8
mov si,dwName
cld
@@01: lodsw
int 29h
mov al,ah
int 29h
lodsw
int 29h
mov al,ah
int 29h
pop ax
push cx
mov cx,4
@@02: ror ax,4
push ax
and ax,0fh
cmp al,10
jb @@03
add al,7
@@03: add al,'0'
int 29h
pop ax
loop @@02
pop cx
loop @@01
ret
dbMess db 10,13,'after interupt',10,13,'$'
dwName dw ' D','I=',' S','I=',' B','P=',' S','P=',' B','X=',' D','X=',' C','X=',' A','X='[/code]
И смотрим результат:
По результатам видно
- Ось не чистит регистры перед запуском программы;
- Любой, повторяю ЛЮБОЙ отладчик чистит РОН'ы(регистры общего назначения), кроме SP;
- Прерывания - изменяют некоторые РОН'ы.
Смотрите, анализируйте - выводы делайте сами.
Ваша программа лечится так:
[code lang=asm] MOV BX, 3E8h
CALL WRITE_DEC
MUL BX
ADD BP, AX[/code]
Еще добавлю, у каждого регистра есть свое назначение - использование ВР, в качестве рабочего регистра - не рекомендуется, т.к. в будущем Вы будете использовать его, к примеру для доступа к параметрам передаными в подпрограмму. Отвыкайте от не целевого использования этого регистра.
Удачи!