0

I'm following the book "Introduction to 64bit Intel Assembly Language Programming for Linux" and one of the tasks is that we should attempt to manually add two floats stored in memory.

In the following solution, I've attempted to calculate the exponent, deducting their respective bias, and then shift each of the floats by them to create a sort of real number which I should be able to add together.

I'm stuck how to feasibly break the sum back into a distinct mantissa and exponent. The book hasn't got to branching, looping, etc. so I'm assuming the author wants this activity done using bit manipulation and integer adding.

; Write an assembly program to perform a product of 2 float values
;; using integer arithmetic and bit operations
;;
;; Start with 2 float values in memory and store the product in memory
;;

                segment .data
float_1         dd              12.5
float_2         dd              12.1

                segment .bss
float_r         resd            1

                segment .text
                global _start

_start:
                ;/* Calculate signage */
                mov             eax, [float_1]
                mov             ebx, [float_2]
                btr             eax, 31         ; determine signage of floats
                setc            cl              ; store sign bit in cl of float 1
                btr             ebx, 31
                setc            ch              ; store sign bit in ch of float 2

                ;/* Determine exponents */
                shr             eax, 23         ; exponent of float 1 in eax/ax/al
                sub             eax, 127        ; deduct bias           

                shr             ebx, 23         ; exponent of float 2 in ebx/bx/bl
                sub             ebx, 127

                ;/* Determine mantissas
                 ;* This includes using exponent to create an integer */
                mov             edx, [float_1]
                and             edx, 0x7FFFFF   ; keep 23 bits at end
                bts             edx, 23         ; create implicit 1
                shl             al              ; shift it left (/ right if -) based on exponent

                mov             eex, [float_2]                  
                and             eex, 0x7FFFFF
                bts             eex, 23
                shl             bl

                ;/* Combine time */
                ; idek what to do here
                ; mov             [float_r], ??  ; save result

                ;/* EOP */
                mov             eax, 1
                xor             ebx, ebx
                int             0x80

Any help would be appreciated. As indicated, I am learning proper 64bit assembly so any general advice is more than welcome too.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
Salih MSA
  • 120
  • 1
  • 7
  • 2
    I doubt it's possible without branching (especially if you want to support denormals, infinities, etc) using integer instructions. Are you sure the book doesn't want you do to it with floating point instructions? I'm also wondering if it's supposed to be 32-bit code (seems odd for an introduction to 64-bit to want 32-bit code). – Brendan Aug 16 '22 at 00:27
  • We haven’t covered them yet and they’re covered explicitly later. Plus the question says only bit stuff and integer arithmetic. If by 32 bit code ur talking about the exit system call, i have no idea why he isn’t using the syscall instruction alternative either – Salih MSA Aug 16 '22 at 00:32
  • 2
    "if exponent is zero { mantissa has no implied bit } else { set the implied bit }" and "if value1's biased exponent is larger than value2's biased exponent { shift value2's mantissa right so the exponents match } else {shift value1's mantissa right so exponents match }" and "if sign flags are the same { I can add mantissas } else { I need to subtract mantissas } " (like `x + -(y) = x - y`). – Brendan Aug 16 '22 at 00:45
  • 1
    Salih MSA, Do you want to also handle Not-a-numbers, Infinity, sub=normals, -0.0 and various rounding modes? – chux - Reinstate Monica Aug 16 '22 at 00:52
  • 1
    32-bit operand-size is totally normal for x86-64, but exiting with eax=1 / `int 0x80` instead of eax=60 / `syscall` is very weird. Also you (or the book) forgot to use `default rel` to make YASM default to `[rel float_1]` for static data instead of the default `[abs float_1]` which is less efficient in 64-bit code. – Peter Cordes Aug 16 '22 at 01:03
  • 1
    Manually would mean by hand ;) What you are doing still counts as automation, despite avoiding dedicated floating point hardware. – Erik Eidt Aug 16 '22 at 03:48
  • @chux-ReinstateMonica at the moment I don’t desire to represent the special float formats – Salih MSA Aug 16 '22 at 03:56
  • @PeterCordes hasn’t been covered yet, will definitely keep that in mind – Salih MSA Aug 16 '22 at 03:57
  • 2
    Have you single-stepped this code? `shl al` doesn't make sense, and doesn't match the comments. It sounds like you're expecting it to work like `shl edx, al`, which is not encodeable. You need the count in CL for variable-count shifts, and it gets masked to a 0..31 range so you can't get negative shifts for free. Also, you need to align the mantissas *with each other* based on the exponent *difference*, not in an absolute sense; you'll just shift all the bits out of both numbers for values that aren't close to 1.0. – Peter Cordes Aug 16 '22 at 05:02
  • 1
    See [Bitwise XOR of floats](https://codegolf.stackexchange.com/a/247235) for an example, although that's golfed (optimized for code size) to the point of being hard to understand. See earlier revisions of the question, and discussion in comments, to better understand the problem. But yeah, you need to handle same vs. different signs. Perhaps you can do that with 2's complement negation of the mantissas according to the sign bits, after shifting them to align (e.g. with the `sar reg,31` / `xor` / `sub` bithack to either negate or do nothing, according to the sign bit.). – Peter Cordes Aug 16 '22 at 05:04
  • 1
    @SalihMSA "I don’t desire to represent the special float formats" --> OK. Yet skipping the edges makes to goal less applicable to general use, – chux - Reinstate Monica Aug 16 '22 at 05:13
  • @PeterCordes once again, thank you very much. Yes, that is a mistake - it’s meant to be ‘shl edx, al’. I hadn’t stepped through the code yet as it was yet another revision, so thanks for these tips honestly. And good idea for the twos complements, i’ll give that a try. – Salih MSA Aug 16 '22 at 13:16
  • @chux-ReinstateMonica understood. I feel slightly out of my depth however, so i’d rather solve one problem at a time. Not like i’ll use my implementation for float addition anyhow – Salih MSA Aug 16 '22 at 13:24
  • 1
    @Brendan Theoretically, all calculations that can be done by a computer can be done by using only the instructions `and`, `not`, `mov` (from and to memory) and `ror` (or `rol`). The only problem is that the program might get very, very long when not using branch instructions. – Martin Rosenau Aug 18 '22 at 17:42

0 Answers0