Деление с остатком

Низкоуровневое программирование портов, микроконтроллеров и т.д.

Модератор: Andy

Marat087
Сообщения: 10
Зарегистрирован: 20 окт 2008, 20:11

27 окт 2008, 20:17

вот собственно сама задача

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

Код: Выделить всё

title РГЗ 3-й вариант
stdin=0
stdout=1
stderr=2
assume	SS:StackSg, DS :D ataSg, 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
Сообщения: 10
Зарегистрирован: 20 окт 2008, 20:11

27 окт 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
Сообщения: 416
Зарегистрирован: 02 ноя 2007, 10:31

28 окт 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         [B] //это байт так что результат в AX будет, а что в DX? (остаток)[/B]
	mov	BX, AX		
	mov	CX, DX[B]//что сюда сохраняем остаток, зачем?[/B]
	pop	AX		
	cwd			
	add	AX, BX		
	adc	DX, CX	
Mov ax,2087 ;ax=2087
Marat087
Сообщения: 10
Зарегистрирован: 20 окт 2008, 20:11

28 окт 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		;вычитаем [B]\\здесь наверняка получится отрицатеьлное значение, как сделать так чтобы в дальнейшем при сложении этот знак учитывался, как я понял надо это значение перевести в дополнительный код[/B]
Аватара пользователя
somewhere
Сообщения: 1837
Зарегистрирован: 31 авг 2006, 17:14
Откуда: 71 RUS
Контактная информация:

28 окт 2008, 16:49

Код: Выделить всё

mov AX, 2807
cbw
Нахрена здесь cbw, если мы заполняем весь AX значением? после cbw регистр AH будет либо 00 либо FF - отсюда ваши мистические 127
It's a long way to the top if you wanna rock'n'roll
airyashov
Сообщения: 416
Зарегистрирован: 02 ноя 2007, 10:31

28 окт 2008, 16:57

Код: Выделить всё

	mov	AX, 2807	;помещаем в АХ число 2807
	cbw [B]//см выше[/B]
	imul	b[B]//умножение на байт так что ax=al*b	[/B]	
	sub	AX, BX
Marat087
Сообщения: 10
Зарегистрирован: 20 окт 2008, 20:11

28 окт 2008, 20:31

все равно чушь получается какаято, дело наверно в выводе результата
Изображение
airyashov
Сообщения: 416
Зарегистрирован: 02 ноя 2007, 10:31

29 окт 2008, 09:46

точно не учитываете знак числа при выводе
приложите весь текс программы, можно на внешней ресурс
airyashov
Сообщения: 416
Зарегистрирован: 02 ноя 2007, 10:31

30 окт 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		[B];вычитаем ax=2807*b, bc=c*x?[/B]

Код: Выделить всё

	mov	AX, e		;заносим в АХ е	
	imul	x		;умножаем на х
тоже самое 135 в байт не вместить (-128...127)
Ответить