flat assembler
Message board for the users of flat assembler.

Index > Windows > FPU crashes with simple operations

Author
Thread Post new topic Reply to topic
rinart73



Joined: 11 Dec 2014
Posts: 16
rinart73 12 Dec 2014, 19:59
Code:
format pe console
entry start

include 'win32a.inc'


section '.text' code executable
  start:
    ;;
    mov eax, 74
    finit
    fld dword[eax]
    fsin
    fstp dword[eax]
    ;;
    invoke  ExitProcess,0


section '.idata' data readable import
  library kernel32, 'kernel32.dll',\
          msvcrt,   'msvcrt.dll'
  import kernel32, ExitProcess, 'ExitProcess'    

Program crashes :/
Post 12 Dec 2014, 19:59
View user's profile Send private message Reply with quote
evk1



Joined: 18 Jun 2014
Posts: 24
evk1 12 Dec 2014, 21:17
The problem is in square brackets. The instruction fld dword[eax] does not means to load eax value to the st0 register but means to load value from the memory location whose address is specified in eax (74) to the st0 register. Windows reserves low addresses for a system usage, so this line should generate something like General Protection Fault or Segmentation Fault. Unfortunately fld cannot loads values directly from general purpose registers, but you can use:
Code:
value_to_load dd 74
...
fld dword [value_to_load]    

or:
Code:
pushd 74
fld dword [esp]
...
fstp dword[esp]
pop eax    

_________________
Sorry for my English
Post 12 Dec 2014, 21:17
View user's profile Send private message Reply with quote
rinart73



Joined: 11 Dec 2014
Posts: 16
rinart73 12 Dec 2014, 21:36
Ok, thank you.
But... how should I store result of "fsin" in memory as float?
:/

Code:
section '.text' code executable
  start:
    ;;
    pushd 33
    fld dword[esp]
    fsin
    fstp dword[esp]
    pop eax
    ;;
    push eax
    push format_f
    call [_printf]
    add esp, 8
    call [_getchar]
    ;;
    invoke  ExitProcess,0


section '.rdata' data readable writeable
  format_f db "%f",10,0    


It writes 74842930642344961000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000.000000

Code:
    mov [n], 13
    fld [n]
    fsin
    fstp [n]
    ;;
    push [n] ; or push n
    push format_f
    call [_printf]
    add esp, 8
    call [_getchar]    

Result is 0.0000
Post 12 Dec 2014, 21:36
View user's profile Send private message Reply with quote
tthsqe



Joined: 20 May 2009
Posts: 767
tthsqe 12 Dec 2014, 22:28
Code:
push    13              ; push integer dword 13 onto memory stack
fild    dword[esp]      ; load this integer into fpu stack
fsin                    ; take sin(13)=0.4201
fstp    dword[esp]      ; pop 0.4201 off of fpu stack and put on stack in memory in the 4 byte locate  created with push 13; this is the second argument of print_f
push    format_f        ; this is the first argument of print_f
call    [_printf]           


Your code should also work if you change fld [n] to fild [n]; you need to tell fpu it to load [n] as an integer, (it does the int->float conversion automatically)
Post 12 Dec 2014, 22:28
View user's profile Send private message Reply with quote
rinart73



Joined: 11 Dec 2014
Posts: 16
rinart73 12 Dec 2014, 23:39
I copied your code and get... :
74842945739140183000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000.000000

Code:
 mov [n], 13
    fild [n]
    fsin
    fstp [n]
    ;;
    push n
    push format_f
    call [_printf    

0.0000

Anyway :<
Post 12 Dec 2014, 23:39
View user's profile Send private message Reply with quote
evk1



Joined: 18 Jun 2014
Posts: 24
evk1 12 Dec 2014, 23:52
I don't understand it. sin should always return value between -1 and 1. It can be rounded to integers -1,1 and 0. But your code returns another values. Try adding finit, but I think it shouldn't help.
Post 12 Dec 2014, 23:52
View user's profile Send private message Reply with quote
evk1



Joined: 18 Jun 2014
Posts: 24
evk1 12 Dec 2014, 23:56
In your latest code you should replace push n with pushd [n]. But, I think it will not solve the problem.

_________________
Sorry for my English
Post 12 Dec 2014, 23:56
View user's profile Send private message Reply with quote
rinart73



Joined: 11 Dec 2014
Posts: 16
rinart73 12 Dec 2014, 23:59
finit - no result
pushd - no result

How can I store calculated value from FPU to some variable or register correctly? Not a integer part, but all value?

UPD:
Ok, this CRAZY construction works(when i place "%d" in format). But not sin
Code:
    finit
    pushd    13              ; push integer dword 13 onto memory stack
    fld    dword[esp]      ; load this integer into fpu stack
    fadd st0,st0                    ; take sin(13)=0.4201
    fstp    dword[esp]      ; pop 0.4201 off of fpu stack and put on stack in memory in the 4 byte locate  created with push 13; this is the second argument of print_f
    pop dword[esp]
    mov eax, [esp]
    push    eax
    push    format_f        ; this is the first argument of print_f
    call    [_printf]
    add esp, 8     


and this for [n]:
Code:
fld [n]
    fadd st0,st0
    mov eax, n
    fstp dword[eax]    


Last edited by rinart73 on 13 Dec 2014, 00:22; edited 1 time in total
Post 12 Dec 2014, 23:59
View user's profile Send private message Reply with quote
evk1



Joined: 18 Jun 2014
Posts: 24
evk1 13 Dec 2014, 00:17
Hmm, 74842945739140183. 17 digits. It seems too large for a float mantissa. Are you sure you are using correct printf version?
Post 13 Dec 2014, 00:17
View user's profile Send private message Reply with quote
rinart73



Joined: 11 Dec 2014
Posts: 16
rinart73 13 Dec 2014, 00:24
Look at my prev. post. It works now... for %d
But I cant calculate sin, because resault will be 0 Sad
Post 13 Dec 2014, 00:24
View user's profile Send private message Reply with quote
evk1



Joined: 18 Jun 2014
Posts: 24
evk1 13 Dec 2014, 00:29
Anyway, IIRC, so large mantissa cannot be used in float. I mean, maybe your printf treats floats as a doubles.
Post 13 Dec 2014, 00:29
View user's profile Send private message Reply with quote
rinart73



Joined: 11 Dec 2014
Posts: 16
rinart73 13 Dec 2014, 01:30
I think, yes
Post 13 Dec 2014, 01:30
View user's profile Send private message Reply with quote
tthsqe



Joined: 20 May 2009
Posts: 767
tthsqe 13 Dec 2014, 04:04
no no. You didn't copy this code correctly. The second instruction should be FILD because you have to convert the integer to float
Code:
push    13              ; push integer dword 13 onto memory stack 
fild    dword[esp]      ; load this integer into fpu stack (CONVERT FROM INT TO FLOAT)
fsin                    ; take sin(13)=0.4201 
fstp    dword[esp]      ; pop 0.4201 off of fpu stack and put on stack in memory in the 4 byte locate  created with push 13; this is the second argument of print_f
push    format_f        ; this is the first argument of print_f 
call    [_printf]           
Post 13 Dec 2014, 04:04
View user's profile Send private message Reply with quote
rinart73



Joined: 11 Dec 2014
Posts: 16
rinart73 13 Dec 2014, 22:01
tthsqe,
1104150528
Post 13 Dec 2014, 22:01
View user's profile Send private message Reply with quote
RIxRIpt



Joined: 18 Apr 2013
Posts: 50
RIxRIpt 13 Dec 2014, 22:35
printf %f requires double (64bit) values in stack.
Code:
;...
sub esp, 8
fstp qword[esp]
push format_f
call [_printf]
add esp, 12
    

http://stackoverflow.com/a/7197619/1901561
Post 13 Dec 2014, 22:35
View user's profile Send private message Visit poster's website Reply with quote
tthsqe



Joined: 20 May 2009
Posts: 767
tthsqe 13 Dec 2014, 22:43
rinart73, I hope you are not losing patience with this thing. It seems that the source of your errors are:
- confusing addresses for the values stored in the addresses
- confusing integers with floating point values
- giving printf a float (DWORD) when you should be giving it a double (QWORD).
I think we might have to be a bit more explicit with RIxRIpt's suggestion:
Code:
push    13            
fild    dword[esp]  
fsin     
sub     esp,4         ; make room for 8 byte double to be passed to printf               
fstp    qword[esp]  ; put the 8 byte double on stack
push    format_f  
call    [_printf] 
    
Post 13 Dec 2014, 22:43
View user's profile Send private message Reply with quote
rinart73



Joined: 11 Dec 2014
Posts: 16
rinart73 13 Dec 2014, 23:54
Yeah! Thank you
Post 13 Dec 2014, 23:54
View user's profile Send private message Reply with quote
CampTheBoss



Joined: 02 Feb 2015
Posts: 42
Location: A chair
CampTheBoss 10 Mar 2015, 08:27
This might be an old post but..

the "%f" used in printf requires a quadword value.

For example, floating 3 gives you "3.000" instead of random numbers which never change.
Post 10 Mar 2015, 08:27
View user's profile Send private message Send e-mail Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.