flat assembler
Message board for the users of flat assembler.

Index > Windows > Dividing negative numbers

Author
Thread Post new topic Reply to topic
lem



Joined: 16 Sep 2013
Posts: 4
lem 20 Sep 2013, 13:32
Code:
format PE console
entry start

include 'win32a.inc'

;=============================
section '.rdata' data readable
;=============================
        pi db 'Liczba PI wynosi: %d.%d', 10, 0
;==============================
section '.text' code executable
;==============================
start:
        push ebp
        mov ebp, esp
        mov eax, 4
        mov [ebp-8], eax        ;znak

        mov eax,  1
        mov [ebp-16], eax       ;mianownik

        mov eax, 2
        mov [ebp-24], eax       ;licznik

        mov eax, 0
        mov [ebp-32], eax       ;wartosc dziesietna pi

        mov eax, 0
        mov [ebp-40], eax

petla:

;       --------------------------
;       dzielenie znaku przez mianownik
        mov eax, [ebp-8]
        mov ebx, [ebp-16]

        xor edx, edx            
        idiv ebx

        add [ebp-32], eax
        add [ebp-40], edx
;       --------------------------
;       zwiekszenie mianownika o 2
        mov eax, [ebp-16]
        add eax, 2
        mov [ebp-16], eax
;       --------------------------
;       negacja znaku
        mov eax, [ebp-8]
        neg eax
        mov [ebp-8], eax
;       --------------------------
;       dekrementacja licznika
        mov eax, [ebp-24]
        dec eax

        mov [ebp-24], eax
        jnz petla

crap:
        mov eax, [ebp-32]
        mov ebx, [ebp-40]
        push ebx                ;przekazanie ebx do printf
        push eax                ;przekazanie eax do printf
        push pi                 ;przekazanie string'a do printf
        call [printf]
        ccall [getchar]         

koniec:
        stdcall [ExitProcess], 0
;====================================
section '.idata' import data readable
;====================================
       library kernel32, 'kernel32.dll', \
                msvcrt,   'msvcrt.dll'
        import kernel32, ExitProcess, 'ExitProcess'
        import msvcrt, printf, 'printf', getchar, '_fgetchar'
    


Hi,
I've got this code, and it should use Leibniz's formula to print out PI number. However, I have no clue why during the second go through the loop everything what i receive in EAX or EDX is simply crap which does not match at all with my calculations. Any clue what i'm doing wrong?

here's cpp version
Code:
#include <iostream>

using namespace std;

int main()
{
    int i;
    cout << "Number of iterations: ";
    cin >> i;
    long int denominator = 1;
    long double pi = 0;
    int sign = 4;

    for(long long int j = 0; j < i; j++)
    {
        pi += (long double) sign / (long double) denominator;
        sign = -sign;
        denominator += 2;
    }
    cout.precision(10);
    cout << "Liczba Pi w przyblizeniu wynosi: ";
    cout << pi;
    return 0;
}
    
Post 20 Sep 2013, 13:32
View user's profile Send private message Reply with quote
AsmGuru62



Joined: 28 Jan 2004
Posts: 1619
Location: Toronto, Canada
AsmGuru62 20 Sep 2013, 13:49
I think you must use FPU to get that correctly done.
This does not look like integer division/addition:
Code:
pi += (long double) sign / (long double) denominator;
    
Post 20 Sep 2013, 13:49
View user's profile Send private message Send e-mail Reply with quote
lem



Joined: 16 Sep 2013
Posts: 4
lem 20 Sep 2013, 13:57
Yeah, so idiv does not does that, does it?
Do you have ideas how to actually use FP in here?
Post 20 Sep 2013, 13:57
View user's profile Send private message Reply with quote
AsmGuru62



Joined: 28 Jan 2004
Posts: 1619
Location: Toronto, Canada
AsmGuru62 20 Sep 2013, 15:14
IDIV will divide EDX:EAX as an integer value, so you get the integer remainder and integer result, like if you divide 10 by 3 you get 3 (RESULT) and 1 (REMAINDER) - all integer.

I will try to make a code sample for FPU.
Post 20 Sep 2013, 15:14
View user's profile Send private message Send e-mail Reply with quote
lem



Joined: 16 Sep 2013
Posts: 4
lem 20 Sep 2013, 15:16
Wow, thanks, i just did not know that idiv works with integers only. Looking forward for that sample and in meantime i'll read this
http://www.website.masmforum.com/tutorials/fptute/index.html
which you've posted somewhere else in the past.
Post 20 Sep 2013, 15:16
View user's profile Send private message Reply with quote
AsmGuru62



Joined: 28 Jan 2004
Posts: 1619
Location: Toronto, Canada
AsmGuru62 20 Sep 2013, 16:07
Here is some working code.
I did not print anything, so you'll have to stop in debugger and check the results.
Code:
; ---------------------------------------------------------------------------
; FILE: GetPI.Asm
; DATE: September 20, 2013
; ---------------------------------------------------------------------------

format  PE GUI 4.0
entry   start
stack   4000h, 4000h

    include 'Win32W.Inc'
    ; {INSMODDEF} Module Definitions inserted immediately before this line

; ---------------------------------------------------------------------------
section '.data' data readable writeable

    double_PI1      dt 0.0
    double_PI2      dt 0.0

; ---------------------------------------------------------------------------
section '.code' code readable executable

    ; {INSMODIMPL} Module Implementations inserted immediately before this line

; ---------------------------------------------------------------------------
virtual at 0
loc1:
    .Long_Sign         dd ?
    .Long_Denominator  dd ?
    .CurrentPi         dt ?  ; 10 bytes DOUBLE
    .Padding           rb 2  ; To align stack on DWORD
    .size = $
end virtual

align 16
GetPI_Entry:
; ---------------------------------------------------------------------------
; INPUT:
;   ECX = # of iterations
;   EDI = address of a DOUBLE value where to put the result (calculated PI)
; ---------------------------------------------------------------------------
    ;
    ; Allocate local variables
    ;
    sub       esp, loc1.size
    mov       esi, esp
    ;
    ; Prepare locals
    ;
    push      1
    pop       eax
    mov       [esi + loc1.Long_Denominator], eax   ; Denominator = 1

    add       eax, 3
    mov       [esi + loc1.Long_Sign], eax          ; Sign = 4

    fldz
    fstp      [esi + loc1.CurrentPi]               ; Pi = 0.0
    ;
    ; Loop the # of iterations in ECX
    ;
.iteration:
    fild      [esi + loc1.Long_Sign]
    fidiv     [esi + loc1.Long_Denominator]
    fld       [esi + loc1.CurrentPi]
    faddp
    fstp      [esi + loc1.CurrentPi]

    neg       [esi + loc1.Long_Sign]
    add       [esi + loc1.Long_Denominator], 2

    loop      .iteration
    ;
    ; Store the result
    ;
    fld       [esi + loc1.CurrentPi]
    fstp      tword [edi]
    ;
    ; Release locals and exit
    ;
    add       esp, loc1.size
    ret

    ; ----------------------------------------------
    ; C++ Equivalent for ABOVE ^^^ (just the calculations)
    ; ----------------------------------------------
    ;int main() 
    ;{ 
    ;    int i; 
    ;    cout << "Number of iterations: "; 
    ;    cin >> i; 
    ;    long int denominator = 1; 
    ;    long double pi = 0; 
    ;    int sign = 4; 
    ;
    ;    for(long long int j = 0; j < i; j++) 
    ;    { 
    ;        pi += (long double) sign / (long double) denominator; 
    ;        sign = -sign; 
    ;        denominator += 2; 
    ;    } 
    ;    cout.precision(10); 
    ;    cout << "Liczba Pi w przyblizeniu wynosi: "; 
    ;    cout << pi; 
    ;    return 0; 
    ;}

; ---------------------------------------------------------------------------
; PROGRAM ENTRY POINT
; ---------------------------------------------------------------------------
align 16
start:
    ;
    ; Try it twice with different # of iterations
    ;
    mov       edi, double_PI1
    mov       ecx, 256
    call      GetPI_Entry

    mov       edi, double_PI2
    mov       ecx, 4096
    call      GetPI_Entry
    ;
    ; Now load them into FPU and compare with 'real' Pi
    ;
    fld       [double_PI2]
    fld       [double_PI1]
    fldpi
    ;
    ; Stop in debugger and look into FPU registers:
    ;
    ; ST0 = Pi calculated by FPU
    ; ST1 = Pi calculated by 256 iterations
    ; ST2 = Pi calculated by 4096 iterations
    ;
    int3
    ;
    ; Get back to Windows
    ;
    invoke    ExitProcess, 0

; ---------------------------------------------------------------------------
section '.idata' import data readable writeable

    library kernel32,'KERNEL32.DLL',user32,'USER32.DLL',gdi32,'GDI32.DLL'

    include 'API\Kernel32.Inc'
    include 'API\User32.Inc'
    include 'API\Gdi32.Inc'
    
Post 20 Sep 2013, 16:07
View user's profile Send private message Send e-mail Reply with quote
lem



Joined: 16 Sep 2013
Posts: 4
lem 20 Sep 2013, 16:19
Yup, I've checked them and they are really good. Thanks a lot, that's a really nice code you did there and it's definitely more advanced than mine crap. However with being more advanced it looks simpler. Anyways, thanks a lot for your work : )
Post 20 Sep 2013, 16:19
View user's profile Send private message 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.