[SOLVED] Signed 64bit multiplication on 32bit machine

Programming, for all ages and all languages.
Gigasoft
Member
Member
Posts: 856
Joined: Sat Nov 21, 2009 5:11 pm

Re: [SOLVED] Signed 64bit multiplication on 32bit machine

Post by Gigasoft »

One should note that if the divisor is 2^32 or greater, you can truncate it to 32 bit precision, and the result will be at most 1 too much. By multiplying with the original divisor, you can see if the answer is larger than the dividend, and if so, subtract 1 from the answer.
HugeCode
Member
Member
Posts: 112
Joined: Mon Dec 17, 2012 9:12 am

Re: [SOLVED] Signed 64bit multiplication on 32bit machine

Post by HugeCode »

I think I have it. Whoo, it will take some time to test it...
EDIT: Ok, I tested, unsigned division works well (but -4/-2=0 rem. -4 :-({|= )
EDIT2: Everything works now (also signed division). Thank you, Brendan.

My final version of code

Code: Select all

;[EBP+4+4] = LOWORD(DIVISOR)
%define ldiv dword [ebp+4+4]
;[EBP+8] = HIWORD(DIVISOR)
%define hdiv dword [ebp+8+4]
;[EBP+12] = LOWORD(NUMERATOR)
%define lnum dword [ebp+12+4]
;[EBP+16] = HIWORD(NUMERATOR)
%define hnum dword [ebp+16+4]
;[EBP-4] = HIWORD(RESULT)
%define hres dword [ebp-4]
;[EBP-8] = LOWORD(RESULT)
%define lres dword [ebp-8]
sl64:
	add eax, eax
	adc edx, edx
	ret
div_sr64:
	mov ebx, hdiv
	shl ebx, 31
	shr hdiv, 1
	shr ldiv, 1
	or ldiv, ebx
	ret
int64div:
	push ebp
	mov ebp, esp
	sub esp, 8
	
	xor edi, edi
	
	cmp hnum, 0
	jns .next1
	
	not lnum
	not hnum
	add lnum, 1
	adc hnum, 0
	mov edi, 1
	
	.next1:
	cmp hdiv, 0
	jns .go0
	
	not ldiv
	not hdiv
	add ldiv, 1
	adc hdiv, 0
	sub edi, 1
	
	.go0:
	;PREAMBULE
	xor eax, eax
	or eax, ldiv
	or eax, hdiv
	cmp eax, 0
	jnz .go1
        ;INTERRUPT
	int 0x0
	
	.go1:
	cmp hdiv, 0
	jnz .go2
	mov eax, lnum
	mov edx, hnum
	div ldiv
	mov ecx, edx
	xor edx, edx
	xor ebx, ebx
	jmp .not_it_all
	
	.go2:
	xor eax, eax
	or eax, lnum
	or eax, hnum
	cmp eax, 0
	jnz .go3
	xor eax, eax
	xor edx, edx
	xor ecx, ecx
	xor ebx, ebx
	ret
	
	.go3:
	mov lres, 0
	mov hres, 0
	
	xor ecx, ecx
	mov eax, ldiv
	mov edx, hdiv
	.winterfell:
		test edx, 1<<31
		jnz .ned_stark
		
		call sl64
		inc ecx
		jmp .winterfell
	
	.ned_stark: ;brace yourself, 64bit division is comming
	mov ldiv, eax
	mov hdiv, edx
	mov eax, lnum
	mov edx, hnum
	.kings_landing:
		xor ebx, ebx
		or ebx, eax
		or ebx, edx
		cmp ebx, 0
		jz .the_king_of_the_north
		
		cmp edx, hdiv
		js .lets_kill_starks
		ja .lannisters_still_here
		cmp eax, ldiv
		js .lets_kill_starks
		
		.lannisters_still_here:
		sub eax, ldiv
		sbb edx, hdiv
		bts lres, ecx
		
		.lets_kill_starks:
		jecxz .the_king_of_the_north
		call div_sr64
		dec ecx
		jmp .kings_landing
		
	.the_king_of_the_north:
	mov ebx, edx
	mov ecx, eax    ;remainder
	mov edx, hres	
	mov eax, lres	;result
	
	.not_it_all:
	test edi, 1
	jz .end
	
	not ecx
	not ebx
	add ecx, 1
	adc ebx, 0
	
	not eax
	not edx
	add eax, 1
	adc edx, 0
	
	.end:	
	mov esp, ebp
	pop ebp
	ret
Post Reply