Re: my first .dll: why doesn't it work ...

From: Ro (inp_out_at_sim.tim)
Date: 11/29/04


Date: Mon, 29 Nov 2004 09:31:43 GMT

Someone have found errors in fpow10i and in bcdtostring
How many errors do you see?
    
; This program is free software; you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation; either version 2 of the License, or
; (at your option) any later version.
;
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with this program; if not, write to the Free Software
; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
;
; *Non* e' consentito usare le funzioni atou, atoi, uPrint, utoa,
; itoa, utoh, hPrint, AsciiToSt0, converti_exp, converti, _mult10,
; St0ToAscii, BcdToString, round, IncArray scritte qui sotto
; per usi militari o di spionaggio o nei campi biologico (quindi
; anche gentica), farmaceutico, nucleare
    
; con a6
; nasm -f obj prog.asm
; alink -oPE prog.obj dlg.res
section .text use32
section .data use32
section .const use32
section .bss use32
section .text
section .data
    
%macro str 2+
    [section .data]
    align 4 , db 0
    %1 db %2
    dd 0
    __SECT__
%endmacro
    
%define NL 13, 10
%define STDIN -10
%define STDOUT -11
%define IDI_ICON 100
%define IDR_MENU 2000
%define IDM_RANDOM 2001
%define IDM_MAX_RANDOM 2002
%define IDM_RANGE_RANDOM 2003
%define IDM_GAUSS 2004
%define IDM_LINEARE 2007
%define IDM_LINEARE1 2008
    
%define IDM_EXIT 2005
%define IDM_HELP_ABOUT 2006
%define IDC_ARROW 07f00h
    IDCANCEL equ 2h
    
    extern ReadFile, WriteFile, GetStdHandle, ExitProcess
    import ReadFile kernel32.dll
    import WriteFile kernel32.dll
    import GetStdHandle kernel32.dll
    import ExitProcess kernel32.dll
    extern GetModuleHandleA, GetTickCount
    import GetModuleHandleA kernel32.dll
    import GetTickCount kernel32.dll
    extern DialogBoxParamA, EndDialog, MessageBoxA, SetDlgItemTextA
    import DialogBoxParamA user32.dll
    import EndDialog user32.dll
    import MessageBoxA user32.dll
    import SetDlgItemTextA user32.dll
    extern LoadIconA, LoadCursorA, RegisterClassA, LoadMenuA,
ShowWindow
    import LoadIconA user32.dll
    import LoadCursorA user32.dll
    import RegisterClassA user32.dll
    import LoadMenuA user32.dll
    import ShowWindow user32.dll
    extern CreateWindowExA, DestroyWindow, PostQuitMessage,
UpdateWindow
    import CreateWindowExA user32.dll
    import DestroyWindow user32.dll
    import PostQuitMessage user32.dll
    import UpdateWindow user32.dll
    extern TranslateMessage, DispatchMessageA, GetMessageA
    import TranslateMessage user32.dll
    import DispatchMessageA user32.dll
    import GetMessageA user32.dll
    extern DefWindowProcA, ReleaseDC, wsprintfA
    import DefWindowProcA user32.dll
    import ReleaseDC user32.dll
    import wsprintfA user32.dll
    
    extern SendMessageA, GetDlgItemTextA, LoadBitmapA, BeginPaint
    import SendMessageA user32.dll
    import GetDlgItemTextA user32.dll
    import LoadBitmapA user32.dll
    import BeginPaint user32.dll
    extern GetClientRect, EndPaint, GetDC, FillRect, RedrawWindow
    import GetClientRect user32.dll
    import EndPaint user32.dll
    import GetDC user32.dll
    import FillRect user32.dll
    import RedrawWindow user32.dll
    extern CreateCompatibleDC, SelectObject, BitBlt, DeleteDC,
SetPixel
    import CreateCompatibleDC gdi32.dll
    import SelectObject gdi32.dll
    import BitBlt gdi32.dll
    import DeleteDC gdi32.dll
    import SetPixel gdi32.dll
    
    
; se numero<=limiti => ok altrimenti e' troppo grande
    base dd 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
, 0 , 0 , 0
    seed dd 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
, 0 , 0 , 0
    seed0 dd 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
, 0 , 0 , 0 , 0 , 0
    numero dt -234545.4555599555555e50 , 0.0 , 0.0 , 0.0
    numero1 dt -12344444444444444444.0e5 , 0.0
    num_temp dt 0.0 , 0.0
    str_pnt dd 0
    stringa db "23.85e40" , 0
    titolo db "Numero 80bits" , 0
    buffer times 512 db 0
    dieci dd 10 , 0
    cw_data dw 0000001101111111b
    align 10 , db 0 ; +InF
    piu_oo dd 0 , 0x80000000 , 0x7FFF , 0
    align 10 , db 0 ; -InF
    meno_oo dd 0 , 0x80000000 , 0xffff , 0
; 0 1 2 3 4 5
    dieci_1 dt 1.0 , 10.0 , 100.0 , 1000.0 , 10000.0 , 100000.0
    dt 1.0e6 , 1.0e7 , 1.0e8 , 1.0e9 , 1.0e10 , 1.0e11 , 1.0e12 ,
1.0e13
    dt 1.0e14 , 1.0e15
    dieci_16 dt 1.0 , 1.0e16 , 1.0e32 , 1.0e48 , 1.0e64 ,
1.0e80 , 1.0e96 , 1.0e112
    dt 1.0e128 , 1.0e144 , 1.0e160 , 1.0e176 , 1.0e192 , 1.0e208 ,
1.0e224 , 1.0e240
    dieci_256 dt 1.0 , 1.0e256 , 1.0e512 , 1.0e768 , 1.0e1024 ,
1.0e1280 , 1.0e1536 , 1.0e1792
    dt 1.0e2048 , 1.0e2304 , 1.0e2560 , 1.0e2816 , 1.0e3072 ,
1.0e3328 , 1.0e3584 , 1.0e3840
    dt 1.0e4096 , 1.0e4352 , 1.0e4608 , 1.0e4864 ; 20=0..19
    
    
    WM_INITDIALOG equ 0110h
    WM_COMMAND equ 0111h
    WM_PAINT equ 0fh
    WM_DESTROY equ 2h
    WM_CLOSE equ 10h
    WM_NCPAINT equ 085h
    WM_ERASEBKGND equ 14h
    WM_CTLCOLOREDIT equ 133h
    WM_MOUSEMOVE equ 200h
    WM_NCMOUSEMOVE equ 0A0h
    
    MB_OK equ 0
    MB_SYSTEMMODAL equ 01000h
    EM_SETSEL equ 0b1h
    SRCCOPY equ 0cc0020h
    SW_SHOW equ 5h
    RDW_INVALIDATE equ 01h
    RDW_INTERNALPAINT equ 02h
    RDW_ERASE equ 04h
    WS_EX_CLIENTEDGE equ 200h
    WS_OVERLAPPEDWINDOW equ 0cf0000h
    WS_VISIBLE equ 10000000h
    
    FirstMessage dd 0 , 0 , 0 , 0 , 0 , 0 , 0
    
    struc rect1
    Left resd 1
    Top resd 1
    Right resd 1
    Bottom resd 1
    Stw resd 1
    Sth resd 1
    endstruc
    
%macro rect1_fill 7
    [section .data]
    %1 dd %2
    dd %3
    dd %4
    dd %5
    dd %6
    dd %7
    __SECT__
%endm
    
    struc WindowClass
    style resd 1
    lpfnWndProc resd 1
    cbClsExtra resd 1
    cbWndExtra resd 1
    hInstance resd 1
    hIcon resd 1
    hCursor resd 1
    hbrBackground resd 1
    lpszMenuName resd 1
    lpszClassName resd 1
    endstruc
    
%macro window_fill 11
    [section .data]
    %1
    dd %2
    dd %3
    dd %4
    dd %5
    dd %6
    dd %7
    dd %8
    dd %9
    dd %10
    dd %11
    __SECT__
%endm
    
    window_fill wstr , 3 , MainWindowProc , 0 , 0 , 0 , 0 , 0 , 6 , 0
, WindowClassName
    [section .data]
    WindowClassName db 'Anything' , 0
    WindowCaption db 'Base App' , 0
    __SECT__
    [section .data]
    WindowHandle dd 0 ,0
    MenuHandle dd 0 ,0
    WindowX dd 50 ,0
    WindowY dd 50 ,0
    WindowW dd 500 ,0
    WindowH dd 350 ,0
    __SECT__
    
    [section .text]
    
..start:
    pushad
    push 0
    call [GetModuleHandleA]
    mov [wstr+ hInstance], eax
    push IDI_ICON
    push dword[wstr+hInstance]
    call [LoadIconA]
    mov [wstr+ hIcon] , eax
    push IDC_ARROW
    push 0
    call [LoadCursorA]
    mov [wstr+ hCursor] , eax
    push wstr
    call [RegisterClassA]
    push IDR_MENU
    push dword[wstr+hInstance]
    call [LoadMenuA]
    mov [MenuHandle] , eax
    push 0
    push dword[wstr+hInstance]
    push dword[MenuHandle]
    push 0
    push dword[WindowH]
    push dword[WindowW]
    push dword[WindowY]
    push dword[WindowX]
    push WS_OVERLAPPEDWINDOW | WS_VISIBLE
    push WindowCaption
    push WindowClassName
    push WS_EX_CLIENTEDGE
    call [CreateWindowExA]
    mov [WindowHandle], eax ; 12 argomenti
    push SW_SHOW
    push dword[WindowHandle]
    call [ShowWindow]
    push dword[WindowHandle]
    call [UpdateWindow]
    finit
    jmp short .L1
.While:
    push FirstMessage
    call [TranslateMessage]
    push FirstMessage
    call [DispatchMessageA]
.L1:
push 0
push 0
push 0
push FirstMessage
call [GetMessageA]
    cmp eax, 0
    jne .While
    
    popad
    push 0
    call [ExitProcess]
    
    
    
; void MainWindowProc(Adr, msg, wpar, lpar)
; 0 k, 4 Ra, 8 P_Adr, 12 P_msg, 16 P_wpar, 20 P_lpar
MainWindowProc:
    push ebp
    mov ebp, esp
    %define @Adressee [ebp+8]
    %define @Message [ebp+12]
    %define @wParam [ebp+16]
    %define @lParam [ebp+20]
;---------------------------------------
    cmp dword @Message, WM_CLOSE
    jne .Else_If0
    push dword @Adressee
    call [DestroyWindow]
    mov eax, 1
    jmp .End_If
    
.Else_If0:
cmp dword @Message, WM_DESTROY
jne .Else_If1
    push 0
    call [PostQuitMessage]
    mov eax, 1
    jmp .End_If
    
.Else_If1:
cmp dword @Message, WM_COMMAND
je .cont
    jmp .Else
.cont:
    cmp dword @wParam, IDM_EXIT
    jne .Else_If2
    push 0
    push 0
    push WM_CLOSE
    push dword @Adressee
    call [SendMessageA]
    mov eax, 1
    jmp .End_If
.Else_If2:
cmp dword @wParam, IDM_RANDOM
jne .Else_If3
    fld tword[numero]
    call Tprinth
    mov eax, 1
    jmp .End_If
.Else_If3:
cmp dword @wParam, IDM_MAX_RANDOM
jne .Else_If4
    fld tword[numero1]
    call Tprinth
    mov eax, 1
    jmp .End_If
.Else_If4:
cmp dword @wParam, IDM_RANGE_RANDOM
jne .Else_If5
    push str_pnt
    push stringa
    call AsciiToSt0
    call Tprinth
    mov eax, 1
    jmp .End_If
.Else_If5:
cmp dword @wParam, IDM_GAUSS
jne .Else_If5a
    fld tword[numero]
    push 2
    push 6
    push base
    call St0ToAscii
    fstp st0
; *MessageBoxA( 0, base, base, _ MB_OK || MB_SYSTEMMODAL _ );
    push eax
    push base
    call uPrint
    mov eax, 1
    jmp .End_If
    
.Else_If5a:
cmp dword @wParam, IDM_LINEARE
jne .Else_If5b
    mov eax, 1
    jmp .End_If
.Else_If5b:
cmp dword @wParam, IDM_LINEARE1
jne .Else_If6
    mov eax, 1
    jmp .End_If
.Else_If6:
cmp dword @wParam, IDM_HELP_ABOUT
jne .End_Ifn
    mov eax, 1
    jmp .End_If
.End_Ifn:
    mov eax, 0
    jmp .End_If
    
.Else:
    push dword @lParam
    push dword @wParam
    push dword @Message
    push dword @Adressee
    call [DefWindowProcA]
    
.End_If:
    %undef @Adressee
    %undef @Message
    %undef @wParam
    %undef @lParam
    mov esp, ebp
    pop ebp
    ret 16
    
    
    
    
; eax atou(char* string, char* pos)
; 0 i, 4 r, 8 b, 12 Ra, 16 string, 20 pos
atou:
    push ebx
    push edx
    push esi
    %define @string [esp+16]
    %define @pos [esp+20]
    mov esi, @string
    jmp short .c1
.c0:
inc esi
.c1:
cmp byte[esi], ' '
je .c0
    cmp byte[esi], '+'
    jne .c2
    inc esi
.c2:
cmp byte[esi], '9'
ja .ce
    cmp byte[esi], '0'
    jb .ce
    jmp short .c4
.ce:
mov eax, @pos
mov edx, @string
mov [eax], edx
mov eax, 0
jmp short .cf
.c3:
inc esi
.c4:
cmp byte[esi], '0'
je .c4
    mov eax, 0
    mov ebx, 0
.c5:
mov bl, [esi]
    cmp bl, '9'
    ja .c7
    cmp bl, '0'
    jb .c7
    mul dword[dieci]
    cmp edx, 0
    jne .ci
    sub ebx, '0'
    add eax, ebx
    jc .ci
    inc esi
    jmp short .c5
.ci:
mov eax, 0xFFFFFFFF
.c6:
inc esi
mov bl, [esi]
cmp bl, '9'
ja .c7
    cmp bl, '0'
    jb .c7
    jmp short .c6
.c7:
mov edx, @pos
mov [edx], esi
.cf:
    %undef @string
    %undef @pos
    pop esi
    pop edx
    pop ebx
    ret 8
    
    
; eax atoi(char* string, char* pos)
; 0 i, 4 r, 8 c, 12 b, 16 Ra, 20 string, 24 pos
atoi:
    push ebx
    push ecx
    push edx
    push esi
    %define @string [esp+20]
    %define @pos [esp+24]
    mov esi, @string ; in c il segno
    mov ecx, 0
    jmp short .c1
.c0:
inc esi
.c1:
cmp byte[esi], ' '
je .c0
    cmp byte[esi], '+'
    jne .c2
    inc esi
    jmp short .c3
.c2:
cmp byte[esi], '-'
jne .c3
inc esi
inc ecx
.c3:
cmp byte[esi], '9'
ja .ce
    cmp byte[esi], '0'
    jb .ce
    jmp short .c5
.ce:
mov eax, @pos
mov edx, @string
mov [eax], edx
mov eax, 0
jmp short .cf
.c4:
inc esi
.c5:
cmp byte[esi], '0'
je .c4
    mov eax, 0
    mov ebx, 0
.c6:
mov bl, [esi]
    cmp bl, '9'
    ja .c8
    cmp bl, '0'
    jb .c8
    mul dword[dieci] ; in ci +/-oo
    cmp edx, 0
    jne .ci
    sub ebx, '0'
    add eax, ebx
    jc .ci
    test eax, 0x80000000
    jnz .ci
    inc esi
    jmp short .c6
.ci:
mov eax, 0x7FFFFFFF
.c7:
inc esi
mov bl, [esi]
cmp bl, '9'
ja .c8
    cmp bl, '0'
    jb .c8
    jmp short .c7
.c8:
cmp ecx, 0
jne .c9
neg eax
.c9:
mov edx, @pos
mov [edx], esi
.cf:
    %undef @string
    %undef @pos
    pop esi
    pop edx
    pop ecx
    pop ebx
    ret 8
    
    
; uso: str .titolo, "Numero " ; uPrint(titolo, D*num);
; utoaz( a < char* Title, unsigned n)
; k k= 0k, 4 Ra, 8 1P_Title, 12 1P_n
uPrint:
    push ebp
    mov ebp, esp
    pushad ; sono necessari perche messagebox sembra cambi anche
ecx!!!
    sub esp, 128
    %define @Title [ebp+8]
    %define @n [ebp+12]
    %define @string [esp]
;--------------------*/
    mov eax, @n
    lea ecx, @string
    push eax
    push ecx
    call utoa
    mov eax, @Title
    lea ecx, @string
    push MB_OK | MB_SYSTEMMODAL
    push ecx
    push eax
    push 0
    call [MessageBoxA]
    %undef @Title
    %undef @n
    %undef @string
    add esp, 128
    popad
    mov esp, ebp
    pop ebp
    ret 8
    
    
    
; eax utoa(char* string, unsigned n)
; ritorna in eax i chiars scritti
; 0 k, 4 j, 8 i, 12 r, 16 b, 20 Ra, 24 1P_string, 28 1P_n
utoa:
    push ebx
    push edx
    push esi
    push edi
    push ebp
    %define @string [esp+24]
    %define @n [esp+28]
;--------------------*/
    mov esi, @string
    mov ebx, 10
    mov eax, @n
    mov edi, esi
    mov ebp, 0
.utoaz_l:
    xor edx, edx
    div ebx ; a= (r:a)/b r= (r:a)%b
    add dl, '0'
    mov [edi], dl
    inc edi
    inc ebp
    cmp eax, 0
    jne .utoaz_l
    
    mov byte[edi], 0
    dec edi
    jmp short .vai
.utoaz_f:
    mov al, [esi]
    mov ah, [edi]
    mov [edi], al
    mov [esi], ah
    inc esi
    dec edi
.vai:
    cmp esi, edi
    jb .utoaz_f
    
    mov eax, ebp
.utoaz_z:
    %undef @string
    %undef @n
    pop ebp
    pop edi
    pop esi
    pop edx
    pop ebx
    ret 8
    
    
; eax itoa(char* string, int n)
; ritorna in eax i chiars scritti
; 0 k, 4 j, 8 i, 12 r, 16 b, 20 Ra, 24 1P_string, 28 1P_n
itoa:
    push ebx
    push edx
    push esi
    push edi
    push ebp
    %define @string [esp+24]
    %define @n [esp+28]
;--------------------*/
    mov esi, @string
    mov ebx, 10
    mov eax, @n
    mov ebp, 0
    test eax, 0x80000000
    jz .c0
    neg eax ; a&0x70000000;
    mov byte[esi], '-'
    jmp short .c1
.c0:
mov byte[esi], '+'
.c1:
inc esi
inc ebp
mov edi, esi
.itoaz_l:
    xor edx, edx
    div ebx ; a= (r:a)/b r= (r:a)%b
    add dl, '0'
    mov [edi], dl
    inc edi
    inc ebp
    cmp eax, 0
    jne .itoaz_l
    
    mov byte[edi], 0
    dec edi
    jmp short .vai
.itoaz_f:
    mov al, [esi]
    mov ah, [edi]
    mov [edi], al
    mov [esi], ah
    inc esi
    dec edi
.vai:
    cmp esi, edi
    jb .itoaz_f
    
    mov eax, ebp
.itoaz_z:
    %undef @string
    %undef @n
    pop ebp
    pop edi
    pop esi
    pop edx
    pop ebx
    ret 8
    
    
    
; void utoh(char* Title, uint n)
; scrive 8 chars in Title => 8+1'\0'=9 chars richiesti
; 0-7 digits 8'\0' 9 caratteri in tutto
; 0 a, 4 c, 8 b, 12 i, 16 Ra, 20 1P_Title, 24 1P_n
utoh:
    push eax
    push ecx
    push ebx
    push esi
    %define @n [esp+24]
    %define @Title [esp+20]
    mov ebx, @n
    mov ecx, @Title
    mov esi, ecx
    add esi, 7
.l0:
    mov al, bl
    and al, 0Fh
    add al, '0'
    cmp al, '9'
    jbe .l1
    add al, 7
.l1:
    mov byte[esi], al
    dec esi
    shr ebx, 4
    cmp ecx, esi
    jbe .l0
    
    %undef @n
    %undef @Title
    pop esi
    pop ebx
    pop ecx
    pop eax
    ret 8
    
    
    
    
Tprinth:
    push ebx
    push eax
    fstp tword[num_temp] ; il valore in st0 e levato dallo
stack
    mov ebx, buffer
    push dword[num_temp]
    push ebx
    call utoh ; 32
    add ebx, 8
    mov byte[ebx], '#'
    inc ebx
    push dword[num_temp+4]
    push ebx
    call utoh ; +32
    add ebx, 8
    mov byte[ebx], '#'
    inc ebx
    push dword[num_temp+8]
    push ebx
    call utoh ; +16
    add ebx, 8
    mov byte[ebx], '#'
    inc ebx
    mov byte[ebx], '#'
    inc ebx
    mov byte[ebx], 0
    inc ebx
    push MB_OK | MB_SYSTEMMODAL
    push titolo
    push buffer
    push 0
    call [MessageBoxA]
    pop eax
    pop ebx
    ret
    
    
; uso: str titolo, "Numero " ; hPrint(titolo, D*num);
; utoaz( a < char* Title, unsigned n)
; k= 0k, 4 Ra, 8 1P_Title, 12 1P_n
hPrint:
    push ebp
    mov ebp, esp
    pushad ; sono necessari perche messagebox sembra cambi anche
ecx!!!
    sub esp, 128
    %define @Title [ebp+8]
    %define @n [ebp+12]
    %define @HexprintString [esp]
;--------------------*/
    mov eax, @n
    lea ecx, @HexprintString
    push eax
    push ecx
    call utoh
    mov eax, @Title
    lea ecx, @HexprintString
    push MB_OK | MB_SYSTEMMODAL
    push eax
    push ecx
    push 0
    call [MessageBoxA]
    %undef @Title
    %undef @n
    %undef @HexprintString
    add esp, 128
    popad
    mov esp, ebp
    pop ebp
    ret 8
    
    
; st0 AsciiToSt0(P_string, P_address_then);
; se [P_address_then]==[P_string] allora st0=0 e non e' preso
altrimenti
; il numero e' preso. Utilizza due registri dello stack-fpu
; per k: 0 k, 4Ra, 8P_string, 12P_address
AsciiToSt0:
    push ebp
    mov ebp, esp
    push ebx
    push ecx
    push edx
    push esi
    push edi
    sub esp, 16 ; s=0num0, 4num1, 8sign, 12cw_save
    fnstcw [esp+12]
    fldcw [cw_data] ; resetta tutto + troncamento
; converti scrive nello 2 dd nello stack qui allocato
    mov esi, [ebp+8]
    call converti
    jnc .a0
    mov eax, [ebp+8]
    mov ebx, [ebp+12]
    mov [ebx], eax
    fldz
    jmp .cx
.a0: ; caso non errore
mov [esp+8], ebx
mov eax, 0
    jmp short .c1 ; leva gli spazi
.c0:
inc edi
.c1:
cmp byte[edi], ' '
je .c0
    mov bl, byte[edi]
    cmp bl, 'e'
    je .c2 ; 44.44 e -12455
    cmp bl, 'E'
    jne .c3
.c2: ; in a esponente
call converti_exp
    cmp eax, 4931
    jg .ce_piu_oo
    cmp ecx, 4931
    jg .ce_piu_oo
    cmp eax, -4931
    jl .ce_zero
.c3:
add eax, ecx
; uPrint(titolo, a);
    cmp eax, 4931
    jg .ce_piu_oo
    cmp eax, -4931
    jl .ce_zero
    jmp short .c4
.ce_piu_oo:
cmp dword[esp+8], 0
jne .seielmeno
fld tword[piu_oo]
jmp .cq
.seielmeno:
fld tword[meno_oo]
jmp .cq
.ce_zero:
fldz
jmp .cf
.c4: ; 10^a
call fpow10i
;fist D*nim; uPrint(titolo, D*nim);
    
.c5: ; num, 10^a
fild qword[esp]
;fist D*nim; uPrint(titolo, D*nim);
    
    fmulp st1 ; num*10^a
.cf:
cmp dword[esp+8], 0
je .cq
FCHS
.cq:
mov eax, [ebp+12]
mov [eax], edi
.cx:
fldcw [esp+12]
    add esp, 16
    pop edi
    pop esi
    pop edx
    pop ecx
    pop ebx
    mov esp, ebp
    pop ebp
    ret 8
    
; <j>pos <a>num+sign converti_exp<j>
converti_exp:
    push ebx
    push ecx
    push edx
    push esi
    push ebp
    mov esi, edi
    mov ebx, 0
    mov edx, 0
.c0: ; leva gli spazi
inc edi
cmp byte[edi], ' '
je .c0
    cmp byte[edi], '+'
    jne .c1
    inc edi
    jmp short .c2
.c1:
cmp byte[edi], '-'
jne .c2
inc edi
inc ebx
.c2:
cmp byte[edi], '9'
ja .ce
    cmp byte[edi], '0'
    jb .ce ; nel caso dopo eventuale + o -
    jmp short .c3
.ce:
mov edi, esi
mov eax, 0
jmp .cf
.c3: ; leva gli zeri
jmp short .c5
.c4:
inc edi
.c5:
cmp byte[edi], '0'
je .c4
    mov eax, 0
    mov ecx, 0
    mov ebp, 0
.c6:
mov cl, [edi ]
    cmp cl, '9'
    ja .c8
    cmp cl, '0'
    jb .c8
    mul dword[dieci]
    sub cl, '0'
    add eax, ecx
    cmp eax, 4931
    ja .ck
    inc edi
    jmp short .c6
.ck:
inc edi
mov cl, [edi ]
    cmp cl, '9'
    ja .c8
    cmp cl, '0'
    jb .c8
    jmp short .ck
.c8:
cmp ebx, 1
jne .cf
neg eax
.cf:
    pop ebp
    pop esi
    pop edx
    pop ecx
    pop ebx
    ret
    
; input signed int a; output 10^a in st0
; utilizza due posizioni dello fpu-stack
; non inizializza niente; rounding mode per troncamento
; settato all'esterno
fpow10i:
    push eax
    push ebx
    push ecx
    cmp eax, -4931
    jl .ze
    cmp eax, 4931
    jg .oo
    jmp short .c0
.ze:
fldz
jmp .fine
.oo:
fld tword[piu_oo]
jmp .fine
.c0:
mov ebx, 0
test eax, 0x80000000
jz .c1
neg eax
mov ebx, 1
.c1:
mov ecx, eax
and ecx, 0xF
lea ecx, [ecx+4*ecx]
lea ecx, [2*ecx]
    FLD tword[dieci_1 + ecx]
    mov ecx, eax
    shr ecx, 4
    and ecx, 0xF
    lea ecx, [ecx+4*ecx]
    lea ecx, [2*ecx]
    FLD tword[dieci_16 + ecx]
    mov ecx, eax ; ok poiche' c<=4931
    shr ecx, 8
    FMULP st1
    lea ecx, [ecx+4*ecx] ; e 4931>>8 == 19
    lea ecx, [2*ecx]
    FLD tword[dieci_256 + ecx]
    cmp ebx, 1
    FMULP st1
    jnz .fine
    FLD1
    FDIVRP st1
.fine:
    pop ecx
    pop ebx
    pop eax
    ret
    
; segno in b
; numero nello stack del chiamante in num1:num0 numero
; di cifre in c, ultima posizione in j
; nel caso di errore o nessun numero stc altrimenti clc
; converti<origine i>
; 0 @sign, 4k, 8r, 12 i, 16 a, 20 Ra, 24 num0, 28 num1
converti:
    push eax
    push esi
    push edx
    push ebp ; i punta sempre al carattere
; corrente della stringa
    %define @sign [esp]
    sub esp, 4
    jmp short .c1 ; leva gli spazi
.c0:
inc esi
.c1:
cmp byte[esi], ' '
je .c0
    mov dword @sign, 0
    cmp byte[esi], '+'
    jne .b0
    inc esi
    jmp short .c2
.b0:
cmp byte[esi], '-'
jne .c2
inc esi
inc dword @sign
.c2:
cmp byte[esi], '9'
ja .ce
    cmp byte[esi], '0'
    jb .ce ; nel caso dopo eventuale + o -
    jmp short .b1 ; c'e' un non numero => errore
.ce:
mov edx, 0
mov eax, 0
mov ecx, 0
mov ebx, 0
mov edi, [ esp + 12 ]
jmp .cf
.b1: ; leva gli zeri
jmp short .g1
.g0:
inc esi
.g1:
cmp byte[esi], '0'
je .g0
    mov eax, 0
    mov edx, 0
    mov ebp, 0
    mov edi, 0
    mov ecx, 0
.c3: ; prende parte non esponente
mov al, [esi ]
    cmp al, '9'
    ja .c4
    cmp al, '0'
    jb .c4
    call _mult10
    jc .c7
    sub al, '0'
    add ebp, eax
    jnc .b2
    inc edx
    jno .b2
    sub ebp, eax
    dec edx
    dec ecx
    jnz .c7
.b2:
inc esi
jmp short .c3
.c4:
cmp al, '.'
je .a1
jmp .c9
.a1:
cmp byte[esi+1], '9'
ja .a2
cmp byte[esi+1], '0'
jb .a2
    jmp short .a3
.a2: ; caso numero.?non_numero
jmp .c9
.a3: ; caso numero.?numero
mov edi, esi
.ca: ; elimina gli zeri superflui
inc edi
mov al, [edi ]
    cmp al, '9'
    ja .cb
    cmp al, '0'
    jb .cb
    jmp short .ca
.cb: ; j punta *all'ultimo numero* non zero
dec edi
mov al, [edi ]
cmp al, '0'
je .cb
    cmp esi, edi
    jne .cd ; tranne caso numero.000000000
    jmp .c9
.cd:
cmp esi, edi
je .a0
    inc esi
    mov al, [esi]
    call _mult10 ; elimina i restanti decimali
    jc .a0
    sub al, '0'
    dec ecx
    add ebp, eax
    jnc .a4
    inc edx
    jno .a4
    sub ebp, eax
    dec edx
    jmp short .a0
.a4:
jmp short .cd
    
.c7: ; caso 999etc
inc ecx
inc esi
mov al, [esi ]
    cmp al, '9'
    ja .c8
    cmp al, '0'
    jae .c7
.c8: ; caso 999etc.etc
cmp al, '.'
jne .c9
    cmp byte[esi+1], '9'
    ja .c9
    cmp byte[esi+1], '0'
    jb .c9
.a0:
inc esi
mov al, [esi ]
    cmp al, '9'
    ja .c9
    cmp al, '0'
    jae .a0
.c9:
mov edi, esi
mov ebx, @sign
.cf:
add esp, 4
    cmp edi, [esp+8]
    jne .cc
    stc
    jmp short .cz
.cc: ; [s+8]==i
clc
.cz: ; nello stack la risposta
mov [esp+20], ebp
mov [esp+24], edx
    %undef @sign
    pop ebp
    pop edx
    pop esi
    pop eax
    ret
    
    
; r:k mult10<r:k>
; ma (r:k)*10< 1 0 0 ? clearCarry: setCarry
; 0 j, 4 i, 8 c, 12 b, 16 a, 20 Ra
_mult10:
    push eax
    push ebx
    push ecx
    push esi
    push edi
;------------------*/
    mov ecx, edx ; salva input in c:j
    mov edi, ebp
    mov eax, ebp
    mul dword[dieci] ; k*10
    mov esi, eax ; save result in i:k
    mov ebp, edx
    
    mov eax, ecx
    mul dword[dieci]
    add eax, ebp
    jnc .m0
    inc edx
.m0:
    cmp edx, 0
    jne .mfineset
    mov edx, eax
    mov ebp, esi
    test edx, 0x80000000
    jnz .mfineset
; qui perde un bit per il segno
    clc
    jmp short .mfine
.mfineset:
    mov edx, ecx
    mov ebp, edi
    stc
.mfine:
    pop edi
    pop esi
    pop ecx
    pop ebx
    pop eax
    ret
    
    
; eax St0ToAscii( char* string, uint intPart, uint decPart ) <st0>;
; Suppone che la stringa sia sufficientemente ampia ritorna
; in eax il numero di caratteri scritti usa due registri float
; per intPart=0 scrive il numero senza esponente se l'esponente
; permette (e<17 && e>0) altrimenti (intPart, decPart)=( 1, decPart )
; se intPart o decPart sono fuori range li aggiusta
; privileggiando intPart
; k: 0k, 4 ra, 8 P_string, 12 P_intPart, 16 P_decPart
St0ToAscii:
    push ebp
    mov ebp, esp
    push ebx
    push ecx
    push edx
    push esi
    sub esp, 32 ; 10, 20; 0-9=num, 12-15=exp, 16-17=wc_temp
20-29=bcd
    %define @string [ebp+8]
    %define @exp [esp+12]
    %define @wc_temp [esp+16]
    %define @bcd [esp+20]
    fnstcw @wc_temp
    mov dword[esp+8], 0
    fldcw [cw_data] ; resetta tutto + troncamento
    fxam ; controlla numero in st0 setta c0, c1, c2,
c3
    mov esi, @string
    fnstsw ax ; store in ax content of stauts reg
; 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
; c0 c1 c2 c3
; c1= sign; c3, c2, c0
; non suppo. 0 0 0 formato
; NaN 0 0 1
; Finite num. 0 1 0
; Infinity 0 1 1
; Zero 1 0 0
; Empty reg. 1 0 1
; Denormal 1 1 0
    mov al, ah
    test al, 00000010b
    jz .c0
    mov byte[esi], '-'
    jmp short .c1
.c0:
mov byte[esi], '+'
.c1: ; leva il bit del segno
inc esi
and al, 01000101b
    cmp al, 00000000b
    jne .c2 ; in .cf nessuna operazione in fpu-stack
    dec esi
    mov dword[esi], 'Ns'
    mov eax, 2
    jmp .cf
.c2:
cmp al, 00000001b
jne .c3
    dec esi
    mov dword[esi], 'NaN'
    mov eax, 3
    jmp .cf
.c3:
cmp al, 00000101b
jne .c4
    mov dword[esi], 'InF'
    mov eax, 4
    jmp .cf
.c4:
cmp al, 01000000b
jne .c5
    mov dword[esi], '0.0'
    mov eax, 4
    jmp .cf
.c5:
cmp al, 01000001b
jne .c7
    dec esi
    mov dword[esi], 'Nul'
    mov eax, 3
    jmp .cf
.c6:
mov dword[esi], '0.0'
mov eax, 4
jmp .ca
.c7: ; st = num, num
fld st0
    fstp tword[esp] ; st = num ; salva il numero num
    fxtract ; st = f(num), e(num)
    fstp st0 ; st = e(num)
    fldlg2 ; st = log_10(2),e(num)
    fmulp st1 ; st = log_10(2)*e(num)
    fistp dword @exp ; st = vuoto; salva x in 10^x, pop;
; salva l'esponente
    mov eax, @exp ; in .c6 0.0
    neg eax
    add eax, 17
    cmp eax, 4931
    jg .c6
; 1/10^x * 10^17 = 10^(17-x)=10^a
    call fpow10i ; st = 10^a
    fld tword[esp] ; st = num,10^a
    fmulp st1 ; st = num*10^a
    fbstp tword @bcd ; st = vuoto; numero in memoria
; ^^^^^^^^^^^^^^^^ salva numero in @bcd=[s+20] *come bcd*
; ---------------- scrive nella stringa
    lea eax, @bcd
    mov ebx, @exp
    push dword[ebp+16]
    push dword[ebp+12]
    push ebx
    push eax
    push esi
    call BcdToString
; ---------------- ripristino
.ca: ; ricarica il numero nello fpu-stack
fld tword[esp]
; st = num
.cf:
fldcw @wc_temp
    %undef @string
    %undef @exp
    %undef @wc_temp
    %undef @bcd
    add esp, 32
    pop esi
    pop edx
    pop ecx
    pop ebx
    mov esp, ebp
    pop ebp
    ret 12
    
    
; eax:len
; BcdToString(char* string, char* bcd_number, uint exp, uint intN,
uint decN)
; k == 0k, 4ra, 8@string, 12@bcd_number, 16@exp, 20IntN, 24decN
BcdToString:
    push ebp
    mov ebp, esp
    push ebx
    push ecx
    push edx
    push esi
    push edi
    sub esp, 64
    %define @string [ebp+8]
    %define @bcd_number [ebp+12]
    %define @exp [ebp+16]
    %define @IntN [ebp+20]
    %define @DecN [ebp+24]
    mov edi, esp
    mov esi, @bcd_number
    mov ebx, @exp
    mov edx, esi
    add esi, 8
    mov byte[edi], '0' ; serve per eventuale arrotondamento
    inc edi
    mov al, [esi]
    mov cl, [esi]
    and cl, 0xf
    shr al, 4
    add al, '0'
    add cl, '0'
    cmp al, '0'
    jne .c0
    mov [edi], cl
    inc edi
    dec esi
    jmp short .c1
.c0:
mov [edi], al
inc ebx
mov [edi+1], cl
dec esi
add edi, 2
.c1:
mov al, [esi]
mov cl, [esi]
and cl, 0xf
shr al, 4
add al, '0'
add cl, '0'
    mov [edi], al
    inc edi
    mov [edi], cl
    dec esi
    inc edi
    cmp esi, edx
    jae .c1
    mov byte[edi], 0 ; ora in s[0..17]"0num" il numero di bcd
    mov eax, @IntN
    cmp eax, 0
    je .c2
    jmp .c4
    
.c2: ; b=exp=2<17 c=2, r=15
cmp ebx, 17
ja .c3
    cmp ebx, 0
    je .c3 ; c=1..17
    mov edx, @DecN
    mov ecx, ebx
    jmp short .c5
.c3:
mov ecx, 1
mov edx, @DecN
jmp short .c5
; b=exp, c=IntN, r=DecN
.c4:
mov ecx, @IntN
mov edx, @DecN
.c5:
cmp ecx, 17
jb .c6
mov ecx, 17
.c6: ; a=17-IntN
mov eax, 17
sub eax, ecx
    cmp edx, eax
    jb .c7
    mov edx, eax
.c7:
mov esi, esp
lea edi, [esp+32]
    sub ebx, ecx ; i=s b==exp
    
; nota: c->1..17 r->17-c=0..16
; arrotonda l'array in s nella cifra scelta
    mov eax, edx ; nessun arrotondamento
    add eax, ecx
    cmp eax, 17
    je .c8
    push 5
    push eax
    push esi
    push edi
    call round
    mov esi, edi
; posiziona il punto nell'array
.c8:
mov edi, @string
    
.cm: ; puo' essere 0000num in un bcd?
cmp byte[esi], '0'
jne .cn
    inc esi
    jmp short .cm
.cn:
cmp byte[esi], '0'
jb .co
cmp byte[esi], '9'
ja .co
    jmp short .c9
.co:
mov dword[edi], '0.0'
add edi, 3
jmp short .cc
    
.c9:
mov al, [esi]
mov [edi], al
cmp al, 0
je .cb
inc esi
inc edi
dec ecx
jnz .c9
    cmp byte[esi], 0
    je .cb
    cmp edx, 0
    je .cb ; c=17: fine
    mov byte[edi], '.'
    inc edi
.ca:
mov al, [esi]
mov [edi], al
cmp al, 0
je .cb
inc esi
inc edi
dec edx
jnz .ca
.cb:
cmp ebx, 0
je .cc
    mov byte[edi], 'e'
    inc edi
    push ebx
    push edi
    call itoa
    add edi, eax
.cc:
mov byte[edi], 0
    mov eax, @string
    sub edi, eax
    mov eax, edi
    inc eax
    %undef @string
    %undef @bcd_number
    %undef @exp
    %undef @IntN
    %undef @DecN
    add esp, 64
    pop edi
    pop esi
    pop edx
    pop ecx
    pop ebx
    mov esp, ebp
    pop ebp
    ret 20
    
; eax:len
; round(char* array, char* origin, uint decimal[1..16], uint min)
; k = 0k, 4ra, 8@array, 12@origin, 16@decimal, 20@min
round:
    push ebp
    mov ebp, esp
    push ebx
    push ecx
    push esi
    push edi
    %define @array [ebp+8]
    %define @origin [ebp+12]
    %define @decimal [ebp+16]
    %define @min [ebp+20]
;-----------------------------------
    mov esi, @origin
    mov edi, @array
    mov ebx, @decimal
    mov ecx, @min
    inc ebx
    cmp ecx, 9
    ja .ce
    cmp ecx, 0
    jb .ce
    cmp ebx, 1
    jle .ce
    cmp edi, 0
    je .ce
    cmp esi, 0
    je .ce
    jmp .c0
.ce:
mov eax, 0
jmp .cf
.c0:
add cl, '0'
add esi, ebx
add edi, ebx
    cmp [esi], cl
    jbe .c1
    dec ebx
    push ebx
    push dword @origin
    push dword @array
    call IncArray
    mov eax, ebx
    inc eax
    jmp short .cf
.c1:
cmp [esi], cl
jb .co
.c2:
cmp [esi], cl
jne .c3
    inc esi
    jmp short .c2
.c3:
cmp byte[esi], '9'
ja .co
cmp byte[esi], '0'
jb .co
cmp [esi], cl
jbe .co
    dec ebx
    push ebx
    push dword @origin
    push dword @array
    call IncArray
    mov eax, ebx
    inc eax
    jmp short .cf
.co:
mov esi, @origin
mov edi, @array
.c4:
mov al, [esi]
mov [edi], al
    inc esi
    inc edi
    dec ebx
    jnz .c4
    mov byte[edi], 0
    mov eax, @array
    sub edi, eax
    mov eax, edi
    inc eax
.cf:
    %undef @array
    %undef @origin
    %undef @decimal
    %undef @min
    pop edi
    pop esi
    pop ecx
    pop ebx
    mov esp, ebp
    pop ebp
    ret 16
    
; al:ah char IncNum<al>
IncNum:
    cmp al, '9'
    jne .c0
    mov al, '0'
    mov ah, 1
    jmp short .cf
.c0:
inc al
mov ah, 0
.cf:
    ret
    
; void IncArray(char* string, char* origin, uint pos)
; string='0'+'number', pos in 'number'
; 0j, 4i, 8c, 12a, 16ra, 20@string, 24@origin, 28@pos
; incrementa la stringa di 1, string e' terminata in pos+1
IncArray:
    push eax
    push ecx
    push esi
    push edi
    %define @string [esp+20]
    %define @origin [esp+24]
    %define @pos [esp+28]
;-------------------------------------
    mov eax, @pos
    mov edi, @string
    mov esi, @origin
    add edi, eax
    add esi, eax
    mov ecx, edi
    mov ah, 1
.c0:
mov al, [esi]
cmp al, '0'
jb .ce
cmp al, '9'
ja .ce
    cmp ah, 0
    je .c1
    call IncNum
.c1:
mov [edi], al
cmp edi, @string
je .ce
dec edi
dec esi
jmp short .c0
.ce:
inc ecx
mov byte[ecx], 0
    %undef @string
    %undef @origin
    %undef @pos
    pop edi
    pop esi
    pop ecx
    pop eax
    ret 12
    
    ret
    



Relevant Pages