Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Низкоуровневое программирование > Assembler - Ассемблер (FASM, MASM, WASM, NASM, GoASM, Gas, RosAsm, HLA) и не рекомендуем TASM
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 22.10.2010, 15:45   #11
Vergo
Пользователь
 
Регистрация: 20.09.2010
Сообщений: 38
По умолчанию

Если любой длины и столбиком.. то думаю проще работать с неупаковаными BCD.
Хитрый у вас препод. Да и в сопроцессор любой длины число тоже не запихать. Интересная задачка. Попробую помочь.
Складывают и умножают BCD обычными командами сложения и умножения, только делают десятичную коррекцию после операции.

Например, часть алгоритма может быть такой:
Алгоритм позволяет умножить неупакованое BCD число любой длины на одноразрядное BCD число.

Код:
	xor     dx, dx
L3:        
	mov     al, byte ptr [si]
	mov     ah, byte ptr [di]
	mul     ah
	aam
	add     al, dl
	aaa
	mov     byte ptr [bx], al
	mov     dl, ah

	inc     bx
	dec     si
	loop    L3
	mov     byte ptr [bx], ah
si указывает на первый множитель (на последнюю его цифру)
di - на второй множитель.
В CX длина первого множителя.
Строка результата записывается по адресу [BX] задом наперед. Что для дальнейшего сложения промежуточных результатов даже удобнее.

Преобразовать число из ASCII в неупакованое BCD проще простого:

Код:
	mov     al, 30h
L1:
	sub     [si], al
	inc     si
	loop    L1
В CX длина числа в ASCII формате.
SI указывает на начало ASCII числа. Результат записывается на место исходного числа.

Последний раз редактировалось Vergo; 22.10.2010 в 17:21.
Vergo вне форума Ответить с цитированием
Старый 23.10.2010, 00:46   #12
Alexander_Volk
 
Регистрация: 18.10.2010
Сообщений: 7
По умолчанию

Цитата:
Сообщение от Vergo Посмотреть сообщение

Например, часть алгоритма может быть такой:
Алгоритм позволяет умножить неупакованое BCD число любой длины на одноразрядное BCD число.

Код:
	xor     dx, dx
L3:        
	mov     al, byte ptr [si]
	mov     ah, byte ptr [di]
	mul     ah
	aam
	add     al, dl
	aaa
	mov     byte ptr [bx], al
	mov     dl, ah

	inc     bx
	dec     si
	loop    L3
	mov     byte ptr [bx], ah
si указывает на первый множитель (на последнюю его цифру)
di - на второй множитель.
Хочу внести некоторую ясность. Пожалуйста поправте меня, если ошибаюсь где.
byte ptr[si] - это указывает на наше число любой длины.
byte ptr [di] - это наше то самое одноразрядное BCD число. Если я хочу умножить на число большего разряда(в частности на само себя), то я организовываю ещё один цикл, содержащий в себе вот этот кусок кода.
А вот для работы с этими числами, точнее как их вводить, что бы процессору было понятно, что это именно двоично-десятичное число, а не двоичное, я не совсем разобрался.
Alexander_Volk вне форума Ответить с цитированием
Старый 23.10.2010, 03:01   #13
Vergo
Пользователь
 
Регистрация: 20.09.2010
Сообщений: 38
По умолчанию

Код:
	.model   small
	.stack   100h
size_n   =     30
	.data
b1        db      size_n
sum1    db      0
num1    db      size_n dup (0)

b2        db      size_n
sum2    db      0
num2    db      size_n dup (0)

bufer   db      2*size_n dup (0)
bufer2  db      2*size_n dup (0)

sss     db      0Dh,0Ah,'BBEDITE 1-E CHISLO: $'
sss1    db      0Dh,0Ah,'RESULTAT: $'

	.code
Start:
	mov     ax, @data
	mov     ds, ax
	mov     es, ax
;---------------------------------------
	call    INPUT        
	call    ASCTOBCD
	call    MUL_BCD
	call    PRINT
;---------------------------------------
Exit:
	mov     ax, 04C00h
	int     21h
;---------------------------------------
INPUT PROC       
	mov     ah, 09h
	mov     dx, OFFSET sss
	int     21h
	mov     ah, 0Ah
	mov     dx, OFFSET b1
	int     21h

	inc     byte ptr [sss+0Ah]
	mov     ah, 09h
	mov     dx, OFFSET sss
	int     21h
	mov     ah, 0Ah
	mov     dx, OFFSET b2
	int     21h
	ret
INPUT ENDP
;---------------------------------------
ASCTOBCD PROC
	cld
	mov     al, 30h
	xor     ch, ch
	mov     cl, byte ptr [sum1]
	mov     si, OFFSET num1
L1:
	sub     [si], al
	inc     si
	loop    L1

	xor     ch, ch
	mov     cl, byte ptr [sum2]
	mov     si, OFFSET num2
L2:
	sub     [si], al
	inc     si
	loop    L2
	ret
ASCTOBCD ENDP
;---------------------------------------
MUL_BCD PROC
	mov     si, OFFSET bufer
	push    si

	xor     ch, ch
	mov     cl, byte ptr [sum2]
	mov     di, OFFSET sum2
	add     di, cx
L4:
	mov     bx, OFFSET bufer2
	push    cx
	mov     cl, byte ptr [sum1]
	mov     si, OFFSET sum1
	add     si, cx

	xor     dx, dx
L3:        
	mov     al, byte ptr [si]
	mov     ah, byte ptr [di]
	mul     ah
	aam
	add     al, dl
	aaa
	mov     byte ptr [bx], al
	mov     dl, ah

	inc     bx
	dec     si
	loop    L3
	mov     byte ptr [bx], ah
;-----------------------
	pop     cx
	pop     si
	inc     si

	call    ADD_BCD
	
	push    si

	dec     di
	loop    L4
	pop     si
	ret
MUL_BCD ENDP
;---------------------------------------
ADD_BCD PROC
	push    di
	push    cx
	push    si

	mov     di, OFFSET bufer2

	xor     dx, dx
	mov     cx, size_n
L5:
	xor     ax, ax
	mov     al, byte ptr [si]
	add     al, byte ptr [di]
	aaa
	add     al, dl
	aaa

	mov     byte ptr [si], al
	mov     dl, ah

	inc     si
	inc     di

	loop    L5
	
	mov     byte ptr [si], ah
	
	mov     di, OFFSET bufer2
	mov     cx, size_n
	xor     ax, ax
	cli
	rep stosb

	pop     si
	pop     cx
	pop     di

	ret
ADD_BCD ENDP
;---------------------------------------
PRINT PROC
	mov     si, OFFSET bufer2
	mov     di, si
	mov     cx, size_n*2
L6:
	dec     cx
	dec     si
	mov     al, byte ptr [si]
	cmp     al, 0
	jz      L6
L7:
	or      al, 30h
	mov     byte ptr [di], al
	dec     si
	inc     di
	mov     al, byte ptr [si]
	loop    L7

	mov     byte ptr [di], '$'

	mov     dx, OFFSET sss1
	mov     ah, 09h
	int     21h

	mov     dx, OFFSET bufer2
	mov     ah, 09h
	int     21h

	ret
PRINT ENDP
;---------------------------------------
END     Start
Вот рабочая версия программы, которая выполняет умножение двух чисел любого размера, и именно столбиком, как вы и просили. Правда я позволил себе немножко отойти от стандартного подхода, и складывал промежуточные результаты после умножения на каждый разряд. Это сэкономило немного памяти, дабы не записывать все промежуточные ответы в буфер.
Сейчас ограничитель стоит на 30 разрядов. Если этого недостаточно - нужно изменить значение переменной size_n.
Наверняка это очередной велосипед..причем достаточно корявенький, шлифовать некогда было Проверки на корректный ввод нет, но думаю с доводкой интерфейса у вас проблем не возникнет. Примитивный ввод-вывод осуществлен для проверки работы.
И еще, отрицательные числа я тут не учитывал. Думаю можно сделать проверку на ввод отрицательного числа в момент ввода значений и не усложнять из-за этого всю процедуру.
Извиняюсь за скудность комментов,.. засыпаю уже
Vergo вне форума Ответить с цитированием
Старый 23.10.2010, 15:56   #14
Alexander_Volk
 
Регистрация: 18.10.2010
Сообщений: 7
По умолчанию

Премного благодарен.
У меня как-то и самого простого, но что бы работало как надо не получилось.
Сейчас буду разбираться.
Alexander_Volk вне форума Ответить с цитированием
Старый 23.10.2010, 16:09   #15
Vergo
Пользователь
 
Регистрация: 20.09.2010
Сообщений: 38
По умолчанию

Есть неплохой эмулятор для отладки подобных программ - Emu8086.
Только для него шапку программы нужно немного изменить. Он символ "=" не понимает почему-то.
Начало будет выглядеть так:

Код:
#make_COM#
        ORG  100H 
         
size_n   EQU    30

; Jump to start:
	JMP START

; Data:

b1        db      size_n
sum1    db      0
num1    db      size_n dup (0)

b2        db      size_n
sum2    db      0
num2    db      size_n dup (0)

bufer   db      2*size_n dup (0)
bufer2  db      2*size_n dup (0)

sss      db      0Dh,0Ah,'BBEDITE 1-E CHISLO: $'
sss1    db      0Dh,0Ah,'RESULTAT: $'

Start:
Vergo вне форума Ответить с цитированием
Старый 24.11.2010, 00:11   #16
Alexander_Volk
 
Регистрация: 18.10.2010
Сообщений: 7
По умолчанию

Извиняюсь за некрасивое и долгое отсутствие. За то время пока делал эту лабораторную успел сделать 2 курсовых досрочно.
Вот исходный код с которым я успешно защитился.
Можно было сделать проще и эффективнее, но мне уже просто было не до этого. Потому получился такой очень страшный.
Код:
	.model   small
	.stack   100h
size_n   =     30
	.data
CNTPNT	DB	00 
CURNUM  DB  00 
POSPNT  DB  00
InpBuf1	db	SIZE_N
CNTNUM1 db  ?
NUM1	db	SIZE_N DUP (0)   
InpBuf2	db	SIZE_N     
CNTNUM2 db  ?
NUM2	db	SIZE_N DUP (0)     

POSPNT1	DB	00

RSTMUL1 DB	2*SIZE_N DUP (0)
STRANGE1    DB  2 DUP (0)
RSTMUL2 DB	2*SIZE_N DUP (0)
STRANGE2    DB  2 DUP (0)

InputMsg1	db	0dh,0ah,'Input your first number: ','$'
InputMsg2	db	0dh,0ah,'Input your second number: ','$'

ResMsg	db	0Dh,0Ah,'RESULT:'
DB 3 DUP (0)                                                  
bcd3	db	2*SIZE_N+1 DUP (0)
ThkMsg	db	0dh,0ah,'Thank you for using our program. (c) Volk $'

	.code
Start:
	mov     ax, @data
	mov     ds, ax
	mov     es, ax
	xor	ax, ax
;---------------------------------------
                     
	mov	ah, 09h
	lea	dx, InputMsg1
	int	21h
	mov	ah, 0Ah
	lea	dx, Inpbuf1
	int	21h

	LEA	SI,CNTNUM1
	lea	di, NUM1       
	CALL	CHECK     
	MOV AH,POSPNT
	MOV POSPNT1,AH 
	MOV	POSPNT,00   
	lea	di, NUM1  
	call	ASCIITOBCD    
	XOR CX,CX
	mov CL,CNTNUM1
	lea di,NUM1
	LEA BX,RSTMUL1
	CALL MULBCDP

	mov	ah, 09h
	lea	dx, InputMsg2
	int	21h
	mov	ah, 0Ah
	lea	dx, Inpbuf2
	int	21h 

	LEA	SI,CNTNUM2
	lea	di, NUM2  
	CALL	CHECK   
	lea	di, NUM2
	call	ASCIITOBCD  
	XOR CX,CX
	mov CL,CNTNUM2
	lea di,NUM2
	LEA BX,RSTMUL2
	CALL MULBCDP
	               
	LEA	SI,RSTMUL1
	LEA	DI,RSTMUL2 
	MOV BX,OFFSET BCD3 	                  
	CALL	ADD_BCDINT

	mov	ah, 09h
	lea	dx, ResMsg
	int	21h
EXIT:
	mov	ah,04ch
	int	21h
Alexander_Volk вне форума Ответить с цитированием
Старый 24.11.2010, 00:12   #17
Alexander_Volk
 
Регистрация: 18.10.2010
Сообщений: 7
По умолчанию

Продолжение
Код:
;---------------------------------------

ASCIITOBCD proc
	mov	dh, byte ptr[DI-1]
MINI_LOOP:
    CMP BYTE PTR[DI],2Eh
    JE  SKIP_CONV
	sub	byte ptr[di], 30h
SKIP_CONV:
	inc	di
	dec	dh
	jnz	MINI_LOOP
	ret
ASCIITOBCD ENDP

;---------------------------------------  

CHECK	PROC              
    MOV CURNUM,00 
    MOV CNTPNT,00 
	MOV	dh,byte ptr[SI]
	MOV DL,DH
CHECK_LOOP:              
    INC CURNUM
	MOV	AL,byte ptr[di]
	CMP	AL,30h
	JAE	NEXT_CHECK
	CMP	AL,2Eh
	JE	PNT_CHECK
	JMP	EXIT
PNT_CHECK: 
    CMP CURNUM,1
    JE  EXIT
	CMP	BYTE PTR[DI+1],2Eh
	JE	EXIT       
	MOV AH,CURNUM
	CMP AH,BYTE PTR[SI]
	JE EXIT
	PUSH    AX
	SUB DL,CURNUM
	CMP DL,1
	JE  DEL_PNT
	MOV DL,CURNUM           
	MOV AL,BYTE PTR[DI+1]
	MOV AH,BYTE PTR[DI+2]
	MOV BYTE PTR[DI],AL
	MOV BYTE PTR[DI+1],AH
	INC DL
	MOV BYTE PTR[SI],DL  
	MOV POSPNT,2
	POP AX
	JMP NEXT_CHECK
DEL_PNT:
    MOV DL,CURNUM
    MOV AL,BYTE PTR[DI+1]
    MOV BYTE PTR[DI],AL
    MOV BYTE PTR[SI],DL
    MOV POSPNT,1
    POP AX
NEXT_CHECK:	
	CMP	AL,39h
	JA	EXIT  
	INC DI      
	DEC DH
	JNZ CHECK_LOOP
EXIT_CHECK:
	RET
CHECK	ENDP                       

;---------------------------------------
MulBCDp	proc                      
	add di,cx
	dec di
	mov si,di
	std		;начинаем с младших разрядов
	mov	dh,cl	;запомним исходное
			;состояние счетчика
	push	bx
;заполним буфер результата нулями
	shl	cx,1	;необходим размер 2*SIZE
	xor	al,al	;символ-заполнитель = 0
_null_:
	mov	byte ptr[bx],al
	inc	bx
	loop	_null_
	mov	cl,dh
	pop	bx
;умножение будем проводить "столбиком"
;цикл по всем цифрам первого операнда
_mul_o_:
	xor	dl,dl	;обнулим значение переноса
	push	cx
	push	bx	;сохраним некоторые регистры
	push	si
	mov	cl,dh	;восстановим исходное
			;значение счетчика
;цикл по всем цифрам второго операнда
_mul_i_:
	lodsb		;возьмем очередную цифру
	mul	byte ptr [di]	;умножим
	aam		;коррекция результата
	add	al,dl	;учтем перенос
	aaa
	add	al,[bx]	;сложим с результатом
			;предыдущего умножения
	aaa
	mov	dl,ah	;запомним значение переноса
	xor	ah,ah
	mov	byte ptr[bx],al	;сохраним результат
	inc	bx                               
	loop	_mul_i_
	mov	byte ptr[bx],dl
	pop	si	;восстановим регистры
	pop	bx
	inc	bx
	dec	di	;перейдем к следующей
			;цифре второго операнда
	pop	cx
	loop	_mul_o_
	ret
MULBCDP	endp

;---------------------------------------
ADD_BCDINT PROC  
    XOR CX,CX
    XOR AX,AX 
    MOV AL,CNTNUM1  
    MOV DH,2
    MUL DH
    MOV DH,AL
    MOV AL,CNTNUM2 
    MOV DL,2
    MUL Dl
    MOV DL,AL
    PUSH    DX
    MOV AL,POSPNT1  
    MOV DH,2
    MUL DH
    MOV POSPNT1,AL
    MOV AL,POSPNT 
    MOV DL,2
    MUL DL
    MOV POSPNT,AL
    MOV CL,POSPNT1
    MOV AL,POSPNT
    POP DX       
    CMP DH,DL   
    JB FM   
    CALL    ADD_BCD1
    JMP EXIT_ADDINT
FM:
    XCHG SI,DI
    XCHG DH,DL
    XCHG CL,AL
    CALL ADD_BCD1
EXIT_ADDINT:
    RET
ADD_BCDINT ENDP  
;---------------------------------------
ADD_BCD1 PROC    
    CMP CL,AL
    JAE A1
    XCHG    CL,AL
    XCHG    SI,DI
A1:
    PUSH    AX
    XOR AX,AX  
    MOV AL,DH
    ADD BX,AX 
    INC BX    
    POP AX
    PUSH AX
    PUSH CX
    PUSH BX
SUB1_:
    CMP CL,AL
    JAE  SUB_
    MOV CH,AL
    SUB CH,CL  
    ADD DH,AL
    JMP ADD_LOOPINT
SUB_:       
    MOV CH,CL
    SUB CH,AL
    ADD DH,CL    
ADD_LOOPINT:
	MOV	AL,BYTE PTR[SI]
	CMP CH,0
	JNZ SKIP_ADD		
	ADD	AL,BYTE PTR[DI]
	DEC	DL
	INC	DI      
SKIP_ADD:
	ADD	BYTE PTR[BX],AL
	CMP	BYTE PTR[BX],10
	JB	NEXT_ADDINT
	SUB	BYTE PTR[BX],10
	INC	BYTE PTR[BX-1]
NEXT_ADDINT:
	ADD	BYTE PTR[BX],30h
	DEC	BX
	INC	SI  
	CMP CH,0
	JE SKIP2
SKIP1:
    DEC CH
    JNZ  SKIP2      

SKIP2:
	DEC	DH     	
	JNZ	ADD_LOOPINT   
END_LOOPINT:
	CMP	BYTE PTR[BX],0h
	JE	SKIP_ZERROINT
	ADD	BYTE PTR[BX],30h
SKIP_ZERROINT:      
	POP BX
	POP CX
	POP AX    
      CMP CL,4
	JE RET_PNT
	CMP AL,4
	JE RET_PNT2
	CMP CL,2
	JE RET_PNT
	CMP AH,2
	JE RET_PNT2
	JMP ADD_EXIT
RET_PNT2:
	MOV CL,AH
RET_PNT:
	MOV AH,BYTE PTR[BX]
	MOV BYTE PTR[BX+1],AH   
	DEC BX
	DEC CL
	JNZ RET_PNT
	MOV BYTE PTR[BX+1],2Eh
ADD_EXIT:
	RET
ADD_BCD1 ENDP  
;--------------------------------------
END     StarT
Alexander_Volk вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Умножение panuta Microsoft Office Excel 3 31.05.2010 17:42
С теорией я разобрался незнаю как реализовать Valerii Assembler - Ассемблер (FASM, MASM, WASM, NASM, GoASM, Gas, RosAsm, HLA) и не рекомендуем TASM 2 26.01.2010 15:35
Умножение KoBRaAndrey Общие вопросы Delphi 4 03.10.2009 12:23
умножение PAWLO1993 Паскаль, Turbo Pascal, PascalABC.NET 4 29.07.2008 18:55
помогите с теорией в паскале Vitas1234 Помощь студентам 1 25.05.2008 17:55