NASM - The Netwide Assembler
NASM Forum => Example Code => Topic started by: Ferran 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)...
#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:
;-------------------------------------------------------
; 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.
-
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
; --------------------------------------------------------------
; 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.
-
Since you are compiling for x86-64, I recomend not using fp87 instructions. Use SSE:
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