flat assembler
Message board for the users of flat assembler.
Index
> Nonx86 architectures > [ARM] Help on a remainder for a udiv please, x86 translation 
Author 

cwpjr
I should have said this is a unsigned double ( 64bit ) divided by an unsigned single ( 32 but ) routine....


31 Oct 2012, 22:02 

tthsqe
I'm assuming you want this in 32bit mode.
A: 64 bit unsigned (input) B: 32 bit unsigned (input) Q: 64 bit unsigned (output) R: 32 bit unsigned (output) The output is determined so that A=Q*B+R and R<B Code: xor edx,edx mov eax,dword[A+4] div dword[B] mov [Q+4],eax mov eax,dword[A+0] div dword[B] mov [Q+0],eax mov [R],edx 

31 Oct 2012, 23:23 

revolution
cwpjr wrote: I need to get the remainder into r2, Quotient = int ( Divisor / Dividend ) ;UDIV only does this part Remainder = Divisor  Quotient * Dividend ;This part you need to add 

01 Nov 2012, 00:20 

tthsqe
wait, was the goal a translation to ARM, or a translation to x86?


01 Nov 2012, 01:52 

cwpjr
And thanks so much for the help.
Translating from the x86 commented out code to arm and the output is specified as: r2 = u32REMAINDER, r0 = u32QUOTIENT Again thanks for you kind considerations... The comments are so succinct. Sorry about the target confusion, that's why I edited the original subject with [ARM] and posted in the Nonx86 architectures thread... smile. _________________ Developing ARM Electronic Hobby Bench Stuff! 

01 Nov 2012, 02:05 

cwpjr
revolution wrote:
So I see this possibility... mov r1, r0 ; save divisor udiv r0, r0 , r4 ; r0 is QUOTIENT of divisor(r0) / dividend HI(r4) MLS r2, r0, r2, r1 ; r2 is remainder as divisor(r1)  quotient (r0) * dividend LO(r2) But my math savant tells me beware here....HELP! I love computers because once i get it right they do math for me! In other words I suck at math and appreciate the crutch! _________________ Developing ARM Electronic Hobby Bench Stuff! 

01 Nov 2012, 04:14 

revolution
Are you doing 64bit or 32bit computations? You seem to be mixing things up there. If your values are 64bit then you can't simply use the 32bit instructions like that. Instead you will need to write a full 64by64 divider.


01 Nov 2012, 04:29 

cwpjr
FIRST LET ME POST THE 16 BIT X86 ROUTINE I'M TRYING TO TRANSLATE TO 32BIT ARM THUMB2 CODE:
(; COMMENTS ARE MINE, IT CAME WITH NONE) POP BX ; UMSW POP BX dividendHI POP DX ; ULSW POP DX dividendLO POP AX ; U32 POP AX divisor CMP DX,BX ; DIV BY 0 IF BOTH DIVIDENDS ARE 0? JNB DZERO DIV AX,BX ; SOMEHOW INCLUDES DX? ; AND LEAVES DX AS MODULO? JMP DPUSH ; SAVE DX AND AX DZERO: MOV AX,1 MOV DX,AX JMP DPUSH ; SAVE DX AND AX AS FAR AS I CAN TELL THE ABOVE ORIGINAL X86 CODE IS 16 BIT WHERE THE DOUBLE IS TWO 16 BIT UNSIGNED NUMBERS AND THE DIVIDEND IS A 16 BIT UNSIGNED NUMBER. ; HERE ARE COMMENTS FROM X86 ISA REFERENCE ;when operand is a word: DIV AX,DX ;AX = (DX AX) / operand ;DX = remainder (modulus) LIKE THE ABOVE MY 32 BIT SPEC FOR THIS ROUTINE IS MIXED  THE DIVIDEND IS A UNSIGNED 64 BIT NUMBER WHERE 1  0 1 (BOTH 32 BITS) AND THE DIVISOR IS A 32BIT UNSIGNED NUMBER. THE QUOTIENT IS RESULT IS AN UNSIGNED 32 BIT NUMBER AND THE REMAINDER IS ALSO, AND IF THIS MEANS ANYTHING IT IS CALLED A MODULO. I AM TRYING TO IMPLEMENT THIS AS A 32 BIT VERSION. THE 16 BIT X86 VERSION SEEMS TO USE ONE INSTRUCTION... HOPE THIS HELPS. SORRY ABOUT ALL CAPS. 

01 Nov 2012, 16:48 

revolution
Okay, so you are doing a 64by32 divide. UDIV can't help you to do it in one instruction because it only takes a single 32bit value for each of the dividend and divisor. You will need to write a full division routine to do what you need. A standard bitwise shift and subtract method is probably the easiest to code and understand. If you need it done quickly because of a performance problem then there are other more efficient methods but I think they are beyond the scope of the topic. Might be good for another topic though.
BTW: I made an error above; I exchanged the dividend and divisor incorrectly. It should of course read: Quotient = int ( Dividend / Divisor ) ;UDIV only does this part Remainder = Dividend  Quotient * Divisor ;This part you need to add 

02 Nov 2012, 03:09 

cwpjr
Thanks, Revolution.
One last though. udiv is giving me a proper 32 / 32 result. however "Remainder = Dividend  Quotient * Divisor ;This part you need to add" does not seen to work for me in a MLA ARM instruction form of any kind. I'm saying I can live with a 32x32 udiv and a 32 remainder/modulo and thought that would work. Thanks, Clyde 

03 Nov 2012, 19:18 

revolution
Does this not work?
Code: ;input ;r0 = dividend ;r1 = divisor ;output ;r2 = quotient ;r3 = remainder udiv r2,r0,r1 ;r2=int(r0/r1) mls r3,r2,r1,r0 ;r3=r0r2*r1 

04 Nov 2012, 00:44 

cwpjr
Revolution I must thank you so much. Since I last coded 10+ years ago, I have developed some dyslexia. My solution was the same as yours but with a dyslexic implementation. It was driving me crazy! And probably not fun for you.
Your kind patience with me has allowed me to both see and correct for my issue, resulting in a wonderful feeling of... YESSSSSS!!!!!! I finally got this dang function working! And now that I know what to correct for I'm just back to having lousy math skills! :>) Clyde 

04 Nov 2012, 20:35 

revolution
Remember to plan for possible division by zero. Depending upon your OS settings it may or may not generate an exception.


05 Nov 2012, 12:22 

cwpjr
YOU BET. The black box system I'm translating from appears to return divide by zero (1) if the dividend msw is zero but anther routine that supposedly uses this routine is a mixed mode multiple/divide and one with modulo output, where both generate results that can't ignore the dividend msw.
I'm learning enough about this crap that I think in a bit I'll write a spec and write my own. Then I am to blame if it is incoherent! Cheers, Clyde 

08 Nov 2012, 16:59 

< Last Thread  Next Thread > 
Forum Rules:

Copyright © 19992020, Tomasz Grysztar. Also on GitHub, YouTube, Twitter.
Website powered by rwasa.