# Issue understanding simple ARM ASM function

I'm a little stuck trying to understand this simple piece of code. It get's a number in R0. The first part seems to be a R0 = abs(R0), but then it get's more difficult. The number of leading zeros is determined, then it's left shifted by that many bits and then it's checked if that is > 0, otherwise 0 is returned. I don't get what the purpose of the entire shifting there is supposed to be and what the Add and additional shift operations are supposed to do there.

``````ROM:0005B7BE ; =============== S U B R O U T I N E =======================================
ROM:0005B7BE
ROM:0005B7BE
ROM:0005B7BE sub_5B7BE
ROM:0005B7BE                 ANDS.W  R2, R0, #0x80000000
ROM:0005B7C2                 IT MI
ROM:0005B7C4                 NEGMI   R0, R0
ROM:0005B7C6                 CLZ.W   R3, R0
ROM:0005B7CA                 LSLS.W  R1, R0, R3
ROM:0005B7CE                 BEQ     retZero
ROM:0005B7D0                 RSB.W   R3, R3, #29
ROM:0005B7D8                 MOV.W   R0, R1,LSL#21
ROM:0005B7E4                 BX      LR
ROM:0005B7E6 ; ---------------------------------------------------------------------------
ROM:0005B7E6
ROM:0005B7E6 retZero
ROM:0005B7E6                 MOV.W   R0, #0
ROM:0005B7EA                 BX      LR
ROM:0005B7EA ; End of function sub_5B7BE
``````
• Have you tried using hex-rays/ghidra decompiler to see the auto decompile results? Jun 9 '20 at 9:47
• If it's so "simple", why do you need help? ;) Jun 9 '20 at 14:06

This is function `dflt` (or `__aeabi_i2d`) from the ARM compiler libraries. It performs a conversion of a 32-bit signed integer in `R0` into a a soft-float double (64-bit floating point value) in `R0:R1`.

An IEEE 754 double consists of a sign bit, 11-bit exponent and 52-bit fraction:

`````` 63  62             52 51                                         0
+------------------------------------------------------------------+
| s | exponent(11)    |           fraction(52)                     |
+------------------------------------------------------------------+
+------------------------------------------------------------------+
|           R1                |             R0                     |
+------------------------------------------------------------------+
31                           0 31                                 0
``````

The value of the number is 2^(e-1023)*1.fraction

The code calculates the exponent and fraction that would approximate the original value and puts it into R0:R1. The magic numbers in shifts are necessary to line up the fraction across the two registers and 1024 is the bias for the exponent.

• Thank you very much, I really appreciate it :) The reason I needed help was that the decompiler probably confused me a little: It didn't pick up R1 at all, so it basically only did a `if(a1 << clz(a1)) return a1 << clz(a1) << 21 else return 0` which is obviously completely wrong. When I looked at the assembly I only focused on R0 and didn't think about a value larger than R0. Lack of experience I guess ;) Jun 9 '20 at 17:24