i'm wondering, how print float numbers in nasm using syscalls in linux. have following code, prints @
section .data num dq 2.0 len equ $ - num section .text global _start _start: mov edx, len mov ecx, num mov ebx, 1 mov eax, 4 int 80h mov eax, 1 int 80h
who make right?
you can use fpu convert float writeable string. following example takes pi (a number quite few digits) and
- separates float integral , fractional part,
- converts integral part bcd number using
fbstp
, - converts bcd number ascii string,
- appends fractional part ascii string repeatedly multiplying 10 , converting produced integral part,
- writes string kernel function 4 (sys-write).
converting integral part bcd number doesn't cover whole range of float. also, desirable stop converting fractional part after amount of steps. , there no error check.
global _start section .bss dec_str: resb 512 section .text double2dec: ; args: st(0): fpu-register convert, edi: pointer string %define control_word word [ebp-2] %define ten word [ebp-4] %define temp word [ebp-4] %define integer qword [ebp-12] push ebp mov ebp, esp sub esp, 12 ; modifying rounding mode fstcw control_word mov ax, control_word or ah, 0b00001100 ; set rc=11: truncating rounding mode mov temp, ax fldcw temp ; load new rounding mode ; separate integer , fractional part & convert integer part ascii fst frndint ; st(0) integer fsub st1, st0 ; integral part in st(0), fractional part in st(1) call fpu2bcd2dec fabs ; make fractional positive (not guaranteed fsub) mov byte [edi], '.' ; decimal point add edi, 1 ; move 10 st(1) mov ten, 10 fild ten fxch ; isolate digits of fractional part , store ascii .get_fractional: fmul st0, st1 ; multiply 10 (shift 1 decimal digit integer part) fist word temp ; store digit fisub word temp ; clear integer part mov al, byte temp ; load digit or al, 0x30 ; convert digit ascii mov byte [edi], al ; append string add edi, 1 ; increment pointer string fxam ; st0 == 0.0? fstsw ax sahf jnz .get_fractional ; no: once more mov byte [edi], 0 ; null-termination asciiz ; clean fpu ffree st0 ; empty st(0) ffree st1 ; empty st(1) fldcw control_word ; restore old rounding mode leave ret ; return: edi points null-termination of string fpu2bcd2dec: ; args: st(0): fpu-register convert, edi: target string push ebp mov ebp, esp sub esp, 10 ; 10 bytes local tbyte variable fbstp [ebp-10] mov ecx, 10 ; loop counter lea esi, [ebp - 1] ; bcd + 9 (last byte) xor bl, bl ; checker leading zeros ; handle sign btr word [ebp-2], 15 ; move sign bit carry flag , clear jnc .l1 ; negative? mov byte [edi], '-' ; yes: store minus character add edi, 1 .l1: mov al, byte [esi] mov ah, al shr ah, 4 ; isolate left nibble or bl, ah ; check leading 0 jz .1 or ah, 30h ; convert digit ascii mov [edi], ah add edi, 1 .1: , al, 0fh ; isolate right nibble or bl, al ; check leading 0 jz .2 or al, 30h ; convert digit ascii mov [edi], al add edi, 1 .2: sub esi, 1 loop .l1 test bl, bl ; bl remains 0 if digits 0 jnz .r1 ; skip next line if integral part > 0 mov byte [edi], '0' add edi, 1 .r1: mov byte [edi], 0 ; null-termination asciiz leave ret ; return: edi points null-termination of string _start: fldpi ; load pi fchs ; change sign mov edi, dec_str call double2dec mov eax,4 ; kernel function sys-out mov ebx,1 ; stdout mov ecx,dec_str ; pointer string mov edx, edi ; edi points null-termination of string sub edx, dec_str ; length of string int 0x80 ; call kernel mov eax,1 ; kernel function sys-exit mov ebx,0 ; exit code, 0=normal int 0x80 ; call kernel
you see number lose precision. special peculiarity of ieee-754 coded floating point numbers.
Comments
Post a Comment