0

I'm trying to build a BMI calculator in Assembly. I'm pretty lost to begin with so if any of this doesn't make any sense at all I apologize in advance. I'm making it with predefined values so I don't even need to request for user input.

I'm using uVision5 and the Legacy Device is NXP, LPC2104. I think this is ARM if that's helpful.

Here is what I have so far, I'm trying to do this equation:

BMI = (weightInPounds * conversionFactor) / (heightInInches * heightInInches)

The rules are I have to have the following data definitions:

  • weightInPounds DCD 150
  • heightInInches DCD 64
  • conversionFactor EQU 703

Here is what I have so far:


                    AREA File1, CODE, READONLY
                ENTRY

                LDR r1,weightInPounds   ;loads weight into r1
                LDR r2,heightInInches   ;loads height into r2
                LDR r3,=conversionFactor ;loads conversion into r3
                MUL r4,r1,r3            ;mult weight by conv factor 
                MUL r5,r2,r2            ;square height
                MOV r0,r5, LSR #r4      ;divide previous 2 and store in r0


stop B stop ;force infinite loop by branching to this line

weightInPounds      DCD   150  ;defines weight
heightInInches      DCD   64   ;defines height
conversionFactor    EQU   703  ;defines conversion factor for BMI calc
 END ;end of program

Here are my problems

  • The line LDR r3,conversionFactor ;loads conversion into r3 doesn't work because EQU isn't the same as DCD but I don't know how to fix it and I've looked everywhere and can't figure it out.
  • The first MUL line doesn't work because of the previously mentioned error.

  • I don't know how to divide by a register... In the Line "MOV r0,r5, LSR #r4 what I'm trying to do is divide like in the equation.

Any help would be greatly appreciated.

artless noise
  • 21,212
  • 6
  • 68
  • 105
wposeyjr
  • 101
  • 5
  • 1
    ARM Multiply and divide instructions: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0553a/BABFADHJ.html – Scott Hunter Feb 20 '16 at 02:50
  • @ScottHunter Thanks so much for replies, when i implemented either 'UDIV' or 'SDIV' I recieved the error "A1854E: Unknown opcode 'SDIV', maybe wrong target CPU?". – wposeyjr Feb 20 '16 at 02:55
  • LPC2104 has an ARM7TDMI core; you don't have a divide instruction. I'd suggest implementing an iterative division subroutine (i.e. subtraction in a loop) - it's not the most efficient approach, but it's certainly the most straightforward. – Notlikethat Feb 20 '16 at 16:25
  • Possible duplicate of [How does one do integer (signed or unsigned) division on ARM?](http://stackoverflow.com/questions/8348030/how-does-one-do-integer-signed-or-unsigned-division-on-arm) Also: [Ultimate ARM fast divide](http://www.chiark.greenend.org.uk/~theom/riscos/docs/ultimate/a252div.txt) – artless noise Feb 20 '16 at 18:37

2 Answers2

1

Check out this division algorithm implemented in ARM assembly for dividing R1 by R2:

CMP             R2, #0
BEQ stop
;check for divide by zero!

MOV             R0,#0         
MOV             R3,#1         
;clear R0 to accumulate result
;set bit 0 in R3, which will be 
;shifted left then right

start
    CMP      R2,R1
    MOVLS    R2,R2,LSL#1
    MOVLS    R3,R3,LSL#1
    BLS      start
;shift R2 left until it is about to
;be bigger than R1
;shift R3 left in parallel in order
;to flag how far we have to go

next
    CMP       R1,R2           ;carry set if R1>R2 (don't ask why)
    SUBCS     R1,R1,R2        ;subtract R2 from R1 if this would
                              ;give a positive answer
    ADDCS     R0,R0,R3        ;and add the current bit in R3 to
                              ;the accumulating answer in R0
    MOVS      R3,R3,LSR#1     ;Shift R3 right into carry flag
    MOVCC     R2,R2,LSR#1     ;and if bit 0 of R3 was zero, also
                              ;shift R2 right
    BCC       next            ;If carry not clear, R3 has shifted
                              ;back to where it started, and we
                              ;can end

stop B stop                   ;exit routine

Original link: https://www.virag.si/2010/02/simple-division-algorithm-for-arm-assembler/

branmcf
  • 11
  • 2
-1

The answer for how to divide a register is this

DIV destination-register, nominator-register, denominator-register

I could have mixed my nominator and denominators around so check the result.

You should avoid using MOV if possible since it can only operate on the first 8 bits of ONE register when loading in a constant or it can take TWO full registers as operands and nothing unusual will happen. This is due to the instruction format in arm. The reason for this is there is 8 bits available for the source and 8 bits for destination addresses and when one of those is a number it can only take 8 bits.

Careful Now
  • 260
  • 1
  • 9