PDA

Просмотр полной версии : Деление с остатком



Marat087
27.10.2008, 20:17
вот собственно сама задача

Проблема с делением если деление происходит без остатка то все работает, только знак почемуто не учитывается,
ну а если деление с остатком то вылазиет какая то ерунда.
И еще как в регистр АХ записать например число 2087


title РГЗ 3-й вариант
stdin=0
stdout=1
stderr=2
assume SS:StackSg, DS:DataSg, CS:CodeSg ;Сегментным регистрам
;присвоены имена сегментов
StackSg segment stack ;начало сегмента стека
db 128 dup(?) ;стек размером 128 байт
StackSg ends ;конец сегмента стека
DataSg segment ;начало сегмента данных
a db ?
b db ?
c db ?
x db ?
y db ?
m db 10 ;множитель при перводе строки в число
Msg db 'Программа расчёта выражения y=135x+((cx-2087*b)/a^2); (1 вариант)',10,10,13,'$'
str1 db 'Клавиша "1" - приступить к решению',0Ah,0AH,0Dh,'Клавиша "2" - выход в DOS',10,10,13,'$'
str2 db 'Клавиша "V" - вывод результата на другую видеостраницу',10,10,13,'Клавиш а "F" - запись результата в файл',10,10,13,'$'
MsgErr db 'Внимание!!! Деление на 0!! Введите другие данные!',10,10,13,'$'
zaprosA db 'Введите a: $'
zaprosB db 'Введите b: $'
zaprosC db 'Введите c: $'
zaprosX db 'Введите x: $'
probel db 10,10,13,'$'
buf db 8,8 dup (0)
bufout db 9 dup (?)
DataSg ends ;конец сегмента данных
CodeSg segment ;начало сегмента кода
Bxod: ;метка точки входа в программу
mov AX, DataSg ;адрес сегмента данных в АХ
mov DS, AX ;перевод адреса в DSв
mov AH, 09h ;номер функции 21-го прерывания*
lea DX, probel ;адрес строки сообщения в DX
int 21h ;вызов 21-го прерывания-
;-вывод строки на экран
lea DX, Msg
int 21h
lea DX, str1
int 21h

vibor:
mov AH, 07h ;ф-я ввода с клавиатуры без эха
int 21h
cmp AL, '2' ;нажата клавиша 2?
je perexod ;если да, идём на безусловный переход (усл. переход действует только в пределах 128 байт, а безусл. неограниченно)
cmp AL, '1' ;нажата клавиша 1?
jne vibor ;если нет (т.е. любая, кроме 1 или 2), возвращаемся на ввод
je dalee ;если да, идём далее
perexod:jmp vixod
dalee:
mov AH, 09h
lea DX, zaprosA
int 21h
mov AH, 0ah ;ввод с клавиатуры с эхом
lea DX, buf
int 21h
call conv
mov a, DL

mov AH, 09h
lea DX, zaprosB
int 21h
mov AH, 0ah ;ввод с клавиатуры с эхом
lea DX, buf
int 21h
call conv
mov b, DL

mov AH, 09h
lea DX, zaprosC
int 21h
mov AH, 0ah ;ввод с клавиатуры с эхом
lea DX, buf
int 21h
call conv
mov c, DL

mov AH, 09h
lea DX, zaprosX
int 21h
mov AH, 0ah ;ввод с клавиатуры с эхом
lea DX, buf
int 21h
call conv
mov x, DL

Marat087
27.10.2008, 20:18
Продолжение


;Вычисление выражения:
xor AX,AX
mov AL, a ;помещаем в АL множитель a
cmp AX, 0
jne dalee_1
mov AH, 09h
lea DX, MsgErr
int 21h
jmp dalee
dalee_1:
mov AL, c ;помещаем в AL с
imul x ;умножаем на х
mov BX, AX ;переноси результат из АХ в ВХ
mov AX, 2807 ;помещаем в АХ число 2807
cbw
imul b ;умножаем на b
sub AX, BX ;вычитаем
push AX ;заносим числитель в стек
mov AL, a ;помещаем в AL а
cbw
imul a ;возводим в квадрат
mov BX, AX ;переноси результат из АХ в ВХ
pop AX ;достаем из стека числитель
cwd ;расширяем числитель до двойного слова DX:AX
idiv BX ;делим числитель на знаменатель в АХ-целая часть, в DX-остаток
push BX
push DX
push AX
mov AX, 135
imul x
mov BX, AX ;перемещаем DX:AX в CX:BX
mov CX, DX
pop AX ;достаем из стека целую часть дроби
cwd ;расширяем её до двойного слова DX:AX
add AX, BX ;складываем с ранее найденным произведением
adc DX, CX


;После вычислений в DX:AX-целая часть результата, в стеке DX-остаток от деления и ВХ-знаменатель дроби

;Конвертируем DX:AX в строку десятичных цифр


mov SI, DX ; сохраняем старшее слово в SI
mov BX, 10 ; делитель
mov CX, SP ; в СХ запоминаем вершину стека
big:
cmp DX, BX ; Войдёт ли результат деления в 16 бит?
jb smal ; да, DX < BX, так что результат уместится в AX!

xchg AX, SI ; старшее слово - в AX, сохраняем младшее слово в SI
xor DX, DX ; обнуляем DX
div BX ; делим старшее слово, остаток помещается в DX
xchg AX, SI ; меняем обратно
div BX ; делим младшее слово
push DX ; сохраняем остаток (0..9) в стек!
mov DX, SI ; prepare for next round
jmp big

smal: ; Remainder fits in lower 16 bits (AX)
div bx ; Divide, result stays in AX, remainder in DX
push dx ; Save remainder
xor dx,dx ; Prepare for next round
test ax,ax ; Any more digits?
jnz smal

; Все цифры собраны в стеке, теперь выводим их в строку:
mov DI, offset bufout
store:
pop ax
add al,'0'
mov [di],al
inc di
cmp cx,sp
jne store
mov al, '$'
mov [DI], al
mov AH, 09h
mov DX, offset bufout
int 21h

vixod:
mov AH, 4Ch ;номер функции 21-го прерывания*
int 21h ;передача управления в DOS

conv proc
mov DI, 0
lea BX, buf+1 ;В ВХ адрес второго элемента буфера
mov CX, [BX] ;в СХ кол-во введённых символов
xor CH, CH ;Обнуляем СН
mov SI, 1 ;в SI множитель
met:
push SI ;сохраняем SI (множитель) в стеке
mov SI, CX ;в SI помещаем номер текущего символа
mov AX, [BX+SI] ;в АХ помещаем текущий символ
xor AH, AH ;обнуляем АН
pop SI ;Извлекаем множитель (SI) из стека
sub AX, 30h ;получаем из символа (АХ) цифру
mul SI ;умножаем цифру (АХ) на множитель (SI)
add DI, AX ;складываем с результирующим числом
mov AX, SI ;помещаем множитель (SI) в АХ
mul m ;увеличиваем множитель (АХ) в 10 раз
mov SI, AX ;перемещаем множитель (АХ) назад в SI
loop met ;переходим к предыдущему символу
mov AH, 09h
lea DX, probel
int 21h
mov DX, DI
ret
conv endp
CodeSg ends; конец сегмента кода
end Bxod; конец программы с точкой входа

airyashov
28.10.2008, 09:57
смотрел невнимательно, но вот здесь вроде ошибка

imul a ;возводим в квадрат
mov BX, AX ;переноси результат из АХ в ВХ
pop AX ;достаем из стека числитель
cwd ;расширяем числитель до двойного слова DX:AX
idiv BX ;делим числитель на знаменатель в АХ-целая часть, в DX-остаток
push BX
push DX
push AX
mov AX, 135
imul x //это байт так что результат в AX будет, а что в DX? (остаток)
mov BX, AX
mov CX, DX//что сюда сохраняем остаток, зачем?
pop AX
cwd
add AX, BX
adc DX, CX


Mov ax,2087 ;ax=2087

Marat087
28.10.2008, 16:39
Это я исправил, вроде считает. Но если в АХ забить число 2087, 135 то выдает что то непонятное, ну а если ставить что нибудь меньше 127 то все считает нормально.
Вот еще

dalee_1:
mov AL, c ;помещаем в AL с
imul x ;умножаем на х
mov BX, AX ;переноси результат из АХ в ВХ
mov AX, 2807 ;помещаем в АХ число 2807
cbw
imul b ;умножаем на b
sub AX, BX ;вычитаем \\здесь наверняка получится отрицатеьлное значение, как сделать так чтобы в дальнейшем при сложении этот знак учитывался, как я понял надо это значение перевести в дополнительный код

somewhere
28.10.2008, 16:49
mov AX, 2807
cbw

Нахрена здесь cbw, если мы заполняем весь AX значением? после cbw регистр AH будет либо 00 либо FF - отсюда ваши мистические 127

airyashov
28.10.2008, 16:57
mov AX, 2807 ;помещаем в АХ число 2807
cbw //см выше
imul b//умножение на байт так что ax=al*b
sub AX, BX

Marat087
28.10.2008, 20:31
все равно чушь получается какаято, дело наверно в выводе результата
http://portal.esoo.ru/image/pics/64d3856d8ff5d0bb40cc7f7956cc4108.png

airyashov
29.10.2008, 09:46
точно не учитываете знак числа при выводе
приложите весь текс программы, можно на внешней ресурс

Marat087
29.10.2008, 17:19
http://www.filehoster.ru/files/bq5864

airyashov
30.10.2008, 09:12
dalee_1:
mov AL, c ;помещаем в AL с
imul x ;умножаем на х
mov BX, AX ;переноси результат из АХ в ВХ
mov AX, d ;помещаем в АХ число 2807

imul b ;умножаем на b

ошибка так и не исправлена
ax=0AF7h
умножаем на байт со знаком , т.е al*b=0f7h*1=0fff7h

dalee_1:
mov AL, c ;помещаем в AL с
imul x ;умножаем на х
mov BX, AX ;переноси результат из АХ в ВХ
mov AX, d ;помещаем в АХ число 2807
xor cx,cx
mov cl,b
imul cx ;умножаем на b
sub AX, BX ;вычитаем ax=2807*b, bc=c*x?



mov AX, e ;заносим в АХ е
imul x ;умножаем на х

тоже самое 135 в байт не вместить (-128...127)

airyashov
30.10.2008, 09:48
не в моих правилах, но вот ваш алгоритм вычисления, разберитесь для 1,1,1,1 работает
-2671


;Вычисление выражения:
int 3
xor AX,AX
mov AL, a ;помещаем в АL множитель a
cmp AX, 0
jne dalee_1
mov AH, 09h
lea DX, MsgErr
int 21h
jmp dalee
dalee_1:
mov AL, c ;помещаем в AL с
imul x ;умножаем на х
mov BX, AX ;переноси результат из АХ в ВХ
mov AX, d ;помещаем в АХ число 2807
xor cx,cx
mov cl,b
imul cx ;умножаем на b
sub BX, AX ;вычитаем
push BX ;заносим числитель в стек
mov AL, a ;помещаем в AL а

imul a ;возводим в квадрат
mov BX, AX ;переноси результат из АХ в ВХ
pop AX ;достаем из стека числитель
; xor DX, DX ;обнуляем DX
cwd ;расширяем числитель до двойного слова DX:AX

idiv BX ;делим числитель на знаменатель в АХ-целая часть, в DX-остаток
push BX ;убираем в стек знаменатель
push AX ;убираем в стек целую часть
xor cx,cx
mov cl,x
mov ax, e ;заносим в АХ е
imul cx ;умножаем на х
mov BX, AX ;перемещаем DX:AX в CX:BX

pop AX ;достаем из стека целую часть дроби

;cwd ;расширяем ес до двойного слова DX:AX
add AX, BX ;складываем с ранее найденным произведением