Консультация № 197963
11.03.2020, 22:25
0.00 руб.
0 10 1
Здравствуйте! У меня возникли сложности с таким вопросом:не совпадает результат расчетов com файла, и того же файла но запущеного через debug



Приложение:
[ORG 100h]
;
;
;
;
;
MOV AH, 09h
MOV DX, TXT1
INT 21h
MOV BX, 3E8h ;
CALL WRITE_DEC ;
MUL BX
ADD BP, AX
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 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
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 ; ВОЗВРАТ ИЗ ПРОЦЕДУРЫ
TXT1 DB 'Программа деления двух целых четырехзначных положительных чисел. $'
TXT2 DB ' / $'
TXT3 DB ' = $'
TXT4 DB 13,10,' Остаток от деления = $'

Обсуждение

давно
Старший Модератор
31795
6196
12.03.2020, 12:10
общий
Адресаты:
Цитата: m1dvet
не совпадает результат расчетов

Формулу покажите.

Компилятор какой?
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

давно
Посетитель
403777
4
12.03.2020, 12:21
общий
Адресаты:
Компилятор Nasm, насчет формулы, если я Вас правильно понял то вот она "По запросу программы пользователь вводит с клавиатуры два целых четырехзначных положительных десятичных числа, разделенных знаком операции « / ».Программа выводит на экран результат операции деления
(частное и остаток).
давно
Старший Модератор
31795
6196
12.03.2020, 13:07
общий
Адресаты:

Т.к. Насмом не пользуюсь - не узнал.
Синтаксис Насм похож на Фасм.
Я буду писать на нем.

Написано - "....", Вы вводите четыре цифры- четырьмя вызовами подпрограммам, и поэтому запутываете код.
Код анализировать не стал, сейчас напишу с нуля.
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

давно
Старший Модератор
31795
6196
12.03.2020, 14:35
общий
Адресаты:
Смотрите код:
[code lang=asm]ORG 100h
AG1:
MOV DX, TXT1
call inpNum
jc AG1
push ax
AG2:
MOV DX, TXT2
call inpNum
jc AG2
push ax
mov ah,9
mov dx,TXT3
int 21h
pop di
pop ax
call outReal
xor ax,ax
int 16h
ret
inpNum: mov ah,9
int 21H
xor si,si
xor cx,cx
mov bx,10
IN1: xor ax,ax
int 16h
cmp al,13
jz IN2
cmp al,'0'
jb IN1
cmp al,'9'
ja IN1
push ax
int 29h
pop ax
and ax,0Fh
xchg si,ax
xor dx,dx
mul bx
add si,ax
jmp IN1
IN2: mov ax,si
cmp ax,1000
jb IN3
cmp ax,9999
ja IN3
clc
ret
IN3: mov dx,txt4
stc
ret
outReal:mov bx,10
xor dx,dx
div di
push dx
xor cx,cx
OR1: xor dx,dx
div bx
push dx
inc cx
or ax,ax
jnz OR1
OR2: pop ax
or al,'0'
int 29h
loop OR2
pop ax
mov cx,20
or ax,ax
jz OR4
push ax
mov al,'.'
int 29h
OR3: pop ax
or ax,ax
jz OR4
dec cx
jz OR4
xor dx,dx
mul bx
div di
push dx
or al,'0'
int 29h
jmp OR3
OR4: ret
TXT1 DB 10,13,'enter number A:$'
TXT2 DB 10,13,'enter number B:$'
TXT3 DB 10,13,'A / B = $'
txt4 db 13,10,'enter again:$' [/code]

Работа выглядит так:
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

давно
Посетитель
403777
4
12.03.2020, 15:45
общий
Адресаты:
Большое спасибо Константин Николаевич!!!
давно
Старший Модератор
31795
6196
12.03.2020, 16:06
общий
Адресаты:
Вечером посмотрю Ваш код,
Пока не разобрался почему целая часть не совпадает
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

давно
Посетитель
403777
4
12.03.2020, 21:35
общий
Адресаты:
хорошо, буду очень признателен
давно
Старший Модератор
31795
6196
13.03.2020, 14:10
общий
13.03.2020, 17:07
Адресаты:
Ошибка характерная для всех новичков в ассемблере.

Установка начального значения регистров.
Изменяем Ваш код, добавляем контроль регистра с вводимым числом:
[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]
Вместо ADD - поставить MOV
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

давно
Посетитель
403777
4
13.03.2020, 23:15
общий
Адресаты:
С программой разобрался. Константин Николаевич спасибо за советы и помощь!
давно
Старший Модератор
31795
6196
13.03.2020, 23:31
общий
это ответ
Здравствуйте, 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]

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

Удачи!
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

Форма ответа