1
votes

I am required to write a program in ARM assembly language that takes an integer as input and returns the integer value of that integer times 6.985. For example, if 36 is entered as input then the result will be 251.

I can only use the built in function add (which adds two integers), mul (which multiplies two integers), divide (which divides two integers), getnum (which gets an integer as input from user), and printnum (which prints the output into the screen). My approach is to first multiply by 6985 and then divide by 1000.

Here's my code for the mul function:

bl getnum

mul r0, r0, #6985

bl printnum

Here's my code for the divide function:

bl getnum

mov r1, #1000

bl divide

mov r4, r0

mov r5, r1

bl printnum

mov r0, r5

bl printnum

My question is how can I combine the two method so that it performs multiplication and division at once? I am still new to this language so I don't know how to get rid of the getnum in the divide function and combine it with the mul function.

1
What ARM instruction set and processor family are you using; ARMv7 for Cortex-M4, etc.? Generally, there is no single instruction that does multiplication and division at the same time and some ARM processors don't have a division instruction.InfinitelyManic
If you don't have very exact accuracy requirements, you may do *57221 and then divide the value with 8192 = *6.9849853515625 .. the point is, that 8192 is 2^13, so the division is simple shift-left by 13 bits. (to get better accuracy, just keep multiplying original 6.985 value by 2 till you are happy enough with the decimals to truncate them, and count how many times you multiplied it). Otherwise your approach is valid, not sure what you are asking, just use the result of mul for division part. (and if you go with the powers of 2, try what max number can be multiplied before it overflows)Ped7g
Division by powers of two is of course shift-right, shifting left is multiply by powers of 2.Ped7g
@Ped7g Generally speaking, div/mul by powers of two (2) shifts works, just not all in cases. See publications.ai.mit.edu/ai-publications/pdf/AIM-378.pdfInfinitelyManic
@InfinitelyManic yeah, but that's not a concern in this special case (signed integer * 57221 / 8192 .. for -1 input it will output correct -6). It's always trade of in precision, when dealing with decimal numbers (unless you treat them digit by digit), so you have to be also careful about using *6985 /1000, as it has it's own set of problems (overflow and /1000 truncating).Ped7g

1 Answers

1
votes

To get a whole picture you need to post entire code, including actual definitions of getnum, divide, and printnum.

Let's assume:

  • getnum gets an integer from somewhere (console?) and stores it in r0
  • divide function that is referenced in your code divides r0 by r1, and saves the result in the same registers (not sure what r1 is, perhaps division reminder).
  • printnum just prints out the value of r0.

If my assumption is correct, just combine your code together:

bl getnum

mul r0, r0, #6985
mov r1, #1000

bl divide

bl printnum

Bonus

AFAIK you cannot use the same register for mul command. Not sure if it's applicable to all ARM's or not.