Author Topic: Operate with integer + floating point numbers  (Read 18987 times)

Offline Ferran

  • Jr. Member
  • *
  • Posts: 23
  • Country: ad
Operate with integer + floating point numbers
« on: September 11, 2020, 04:44:21 PM »
I had worry triying how to solve an important issue and finally i did.

In assembly code nothing is obvious, you can't add easly an integer with a floating pointed number as if, or signed and unsigned ones. All its needed to explicit it in the code.

My intention was to do this (in C language)...

Code: [Select]
#include <stdio.h>

/* ---- data section ---- */

    int i = 100;            // We choose an integer to test
    double d = -87.66;      // really we'll a substraction
    double l;
    double res = 0;

/* .... text section ---- */

void main() {

l = i;                      // Convert INT i to DOUBLE l
res = l + d;                // 'add' l +d and move it to res

/* ---- display res ---- */

    printf("Result is:  %g\n", res);    // res = 12.34
}

... but in assembly code. Today i resolved this issue fine and i want to share with you:

Code: [Select]
;-------------------------------------------------------
; itof.asm
;  Conversion INT to DOUBLE number & diplay it
; ------------------------------------------------------
; Assembly with GNU/Linux x80_86) & NASM compiler & GCC
; ------------------------------------------------------
; 1) Compile:  nasm -f elf64 itof.asm
; 2) Link: gcc -no-pie itof.o -o itof
; 3) Run:./itof
; ------------------------------------------------------

bits 64

extern printf

section .data
    i: dq 100                        ; we'll test an int to add to a double
    d: dq -87.66                     ; really we'll rest d minus d
    l: dq 0.0                        ; l will become in the double value of i
    fmt: db "Result is: %g", 10, 0

section .bss
    res: resq   1                    ; 64 bits for res

section .text
global main

main:
push rbp
   
.addition:                           ; int i --> float l ; res=l+d;
        fild        dword [i]      ; conversion from an INT to DOUBLE \o/
fst     qword [l]        ; store the floating point (no pop)
fadd     qword [d]        ; floating add l (to st0)
fstp     qword [res]      ; store into res (pop flt pt stack)

.display:

        mov rdi, fmt             ; address of format string
movq xmm0, qword [res]       ; res score
mov rax, 1               ; 1 argument to print
        call    printf               ; calling printf
 
pop rbp
       
.exit:  mov rax, 0
ret

NOTE: if you wants to do a substraccion, a multiplication or a division you need to change "fadd" by "fsub", "fmul" or "fdiv"

Enjoy it.
« Last Edit: October 01, 2020, 08:07:33 PM by Ferran »

Offline Ferran

  • Jr. Member
  • *
  • Posts: 23
  • Country: ad
Re: Add integer + floating point numbers
« Reply #1 on: October 01, 2020, 08:06:47 PM »
Hello again everybody:

I was working hard about this theme and finally i've a method to work with integers & floating point numbers joined. In other words: you can to add, substract, multiply or divide 2 numers that you need in the order that you like. f.i an integer + float, 2 floats, 2 integers or a float with an intege, whatever.

this is the code of nasmath.asm

Code: [Select]
; --------------------------------------------------------------
; nasmath.asm
; Script to operate with 2 numbers (15.15 and 5)
; Addition, Substraction, Multiplication and Division
; with floating point and integer numbers
;
; Compile: nasm -f elf64 nasmath.asm
; Link: gcc -no-pie nasmath.o -o nasmath
; Run: ./nasmath
; --------------------------------------------------------------

bits 64
extern printf

segment .rodata
CLS: db `\033[2J\033[H`, 0      ; Clean Screen format
LF: db ` `, 10, 0              ; Line Feed format

segment .data
Htitle: db "Operations with 15.15 and 5", 10, 0     ;header
Hsepar: db  "------------------------------", 10, 0 ;separator
 
Maddit: db "Addition    : %g", 10, 0 ;message for addition
Msubst: db "Substraction: %g", 10, 0 ;message for substraction
Mmulti: db "Multiply    : %g", 10, 0 ;message for multiplication
Mdivis: db "Division    : %g", 10, 0 ;message for division
 
Number1: dq 15.15                    ; a floating point number
         Number2: dq 5                        ; an integer number
 
segment .bss
Result: resq 1
 
segment .text
global main
main:

push rbp

; ----------------------- Printing headers -------------------------
lea rdi, [CLS]
xor rax, rax
call printf

lea rdi, [Hsepar]
xor rax, rax
call printf

lea rdi, [Htitle]
xor rax, rax
call printf

lea rdi, [Hsepar]
xor rax, rax
call printf

lea rdi, [LF]
xor rax, rax
call printf

; ----------------------- Addition ----------------------
 
fld    qword [Number1]    ; (1) If Number1 is an integer
fst    qword [Result]     ; change 'fld' by 'fild'
         fild    qword [Number2]    ; (2) If Number2 is a FP
fadd qword [Result]     ; change 'fild' by 'fld'
fstp qword [Result]

lea  rdi, [Maddit]
movq xmm0, qword [Result]
xor  rax, 1
call  printf

; ----------------------- Substraction ------------------
 
fld    qword [Number1]    ; (1)
fst    qword [Result]
         fild    qword [Number2]    ; (2)
fsubr qword [Result]
fstp qword [Result]

lea  rdi, [Msubst]
movq xmm0, qword [Result]
xor  rax, 1
call  printf

; ----------------------- Multiplication ----------------
 
fld    qword [Number1]    ; (1)
fst     qword [Result]
         fild    qword [Number2]    ; (2)
fmul qword [Result]
fstp qword [Result]

lea  rdi, [Mmulti]
movq xmm0, qword [Result]
xor rax, 1
call printf

; ----------------------- Division -----------------------
 
         fild    qword [Number2]    ; (1) *We need reverse the order   
fst qword [Result]     ; of dividend/divisor
fld qword [Number1]    ; (2)
fdiv qword [Result]
fstp qword [Result]

lea rdi, [Mdivis]
movq xmm0, qword [Result]
xor rax, 1
call printf

; ----------------------- Exit ----------------------

pop rbp
mov rax, 0
ret
 

Enjoy it.

Offline fredericopissarra

  • Full Member
  • **
  • Posts: 373
  • Country: br
Re: Operate with integer + floating point numbers
« Reply #2 on: October 02, 2020, 03:26:17 PM »
Since you are compiling for x86-64, I recomend not using fp87 instructions. Use SSE:

Code: [Select]
  bits  64
  default rel

  section .text

  extern __printf_chk

  global  _start
_start:
  cvtsi2sd  xmm0,[i]
  addsd     xmm0,[d]
  mov       edi,1             ; stdout.
  mov       eax,edi           ; 1 extra argument?
  lea       rsi,[fmt]
  call      __printf_chk wrt ..plt

  mov       eax,60
  xor       edi,edi
  syscall

  section .rodata

fmt:
  db  `%f\n`,0

d:
  dq  -87.66

i:
  dd  100