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:54 GMT


Do you like 'my' assembly language?

/* 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 ;

== ReadFile, WriteFile, GetStdHandle, ExitProcess == kernel32.dll
== GetModuleHandleA, GetTickCount == kernel32.dll
== DialogBoxParamA, EndDialog, MessageBoxA, SetDlgItemTextA ==
user32.dll
== LoadIconA, LoadCursorA, RegisterClassA, LoadMenuA, ShowWindow ==
user32.dll
== CreateWindowExA, DestroyWindow, PostQuitMessage, UpdateWindow ==
user32.dll
== TranslateMessage, DispatchMessageA, GetMessageA ==
user32.dll
== DefWindowProcA, ReleaseDC, wsprintfA == user32.dll

== SendMessageA, GetDlgItemTextA, LoadBitmapA, BeginPaint ==
user32.dll
== GetClientRect, EndPaint, GetDC, FillRect, RedrawWindow ==
user32.dll
== CreateCompatibleDC, SelectObject, BitBlt, DeleteDC, 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
db, WindowClassName='Anything', WindowCaption='Base App';
dd, WindowHandle=0, MenuHandle=0, WindowX=50, WindowY=50,
WindowW=500, WindowH=350;

[section .text]

..start:
{pushad
    [wstr+ hInstance] = *GetModuleHandleA(0);
    [wstr+ hIcon] = *LoadIconA( D[wstr+hInstance] , IDI_ICON);
    [wstr+ hCursor] = *LoadCursorA( 0, IDC_ARROW);
    *RegisterClassA(wstr);
    *MenuHandle = *LoadMenuA( D[wstr+hInstance], IDR_MENU );
    *WindowHandle = *CreateWindowExA( WS_EX_CLIENTEDGE,
WindowClassName,
                 WindowCaption, _ WS_OVERLAPPEDWINDOW || WS_VISIBLE _
,
                          D*WindowX, D*WindowY, D*WindowW,
D*WindowH,
                               0, D*MenuHandle, D[wstr+hInstance],
0); /* 12 argomenti
    *ShowWindow( D*WindowHandle, SW_SHOW);
    *UpdateWindow( D*WindowHandle );
     finit; #.L1;
    .While:
        {*TranslateMessage(FirstMessage);
         *DispatchMessageA(FirstMessage);
    .L1: *GetMessageA(FirstMessage, 0, 0, 0);
         a#.While
        }
 popad
   *ExitProcess(0);
}

/* void MainWindowProc(Adr, msg, wpar, lpar)
/* 0 k, 4 Ra, 8 P_Adr, 12 P_msg, 16 P_wpar, 20 P_lpar
MainWindowProc:
{< k
   k = s;
   << @Adressee=[k+8], @Message=[k+12], @wParam=[k+16], @lParam=[k+20]
 /*---------------------------------------
       D @Message == WM_CLOSE !#.Else_If0
                    {*DestroyWindow( D @Adressee ); a=1; ##.End_If; }
      .Else_If0: D @Message == WM_DESTROY !#.Else_If1
                    {*PostQuitMessage(0); a=1; ##.End_If; }
      .Else_If1: D @Message == WM_COMMAND #.cont
                    ##.Else
          .cont:
          { D @wParam == IDM_EXIT !#.Else_If2
            {*SendMessageA( D @Adressee, WM_CLOSE, 0, 0);
              a=1; ##.End_If}
          .Else_If2: D @wParam == IDM_RANDOM !#.Else_If3
            {fld T*numero; Tprinth(); a=1; ##.End_If }
          .Else_If3: D @wParam == IDM_MAX_RANDOM !#.Else_If4
            {fld T*numero1; Tprinth(); a=1; ##.End_If }
          .Else_If4: D @wParam == IDM_RANGE_RANDOM !#.Else_If5
            {AsciiToSt0(stringa, str_pnt); Tprinth(); a=1; ##.End_If }
          .Else_If5: D @wParam == IDM_GAUSS !#.Else_If5a
            {fld T*numero;
             St0ToAscii(base, 6, 2);
             fstp st0;
             uPrint(base, a);
             a=1; ##.End_If
            }
          .Else_If5a: D @wParam == IDM_LINEARE !#.Else_If5b
            {a=1; ##.End_If }
          .Else_If5b: D @wParam == IDM_LINEARE1 !#.Else_If6
            {a=1; ##.End_If }
          .Else_If6: D @wParam == IDM_HELP_ABOUT !#.End_Ifn
            {a=1; ##.End_If }
          .End_Ifn:
           a=0; ##.End_If;
          }
      .Else:
         { *DefWindowProcA( D @Adressee, D @Message, D @wParam, D
@lParam); }
 .End_If:
>> @Adressee, @Message, @wParam, @lParam
  s = k
> k;
 ret 16
}

/* eax atou(char* string, char* pos)
/* 0 i, 4 r, 8 b, 12 Ra, 16 string, 20 pos
atou:
< b, r, i
<< @string=[s+16], @pos=[s+20]
     i=@string; #.c1;
.c0: ++i; .c1: B*i==' '#.c0;
     B*i=='+'!#.c2 | ++i;
.c2: B*i>'9' #.ce;
     B*i<'0' #.ce;
     #.c4;
.ce: a=@pos; r=@string; *a=r; a=0; #.cf;
.c3: ++i; .c4: B*i=='0'#.c4
     a=0; b=0;
.c5: bl=*i;
      bl>'9'#.c7
        bl<'0'#.c7
          mul D*dieci; r#.ci;
          b-='0'; a+=b; jc .ci
          ++i; #.c5;
.ci: a=0xFFFFFFFF;
.c6: ++i; bl=*i; bl>'9'#.c7;
                   bl<'0'#.c7; #.c6
.c7: r=@pos; *r=i;
.cf:
>> @string, @pos
> b, r, i
ret 8

/* eax atoi(char* string, char* pos)
/* 0 i, 4 r, 8 c, 12 b, 16 Ra, 20 string, 24 pos
atoi:
< b, c, r, i
<< @string=[s+20], @pos=[s+24]
     i=@string; c=0; #.c1; /* in c il segno
.c0: ++i; .c1: B*i==' '#.c0;
     B*i=='+'!#.c2 | ++i; #.c3;
.c2: B*i=='-'!#.c3 | ++i; ++c;
.c3: B*i>'9' #.ce;
     B*i<'0' #.ce;
     #.c5;
.ce: a=@pos; r=@string; *a=r; a=0; #.cf;
.c4: ++i; .c5: B*i=='0'#.c4
     a=0; b=0;
.c6: bl=*i;
      bl>'9'#.c8
        bl<'0'#.c8
          mul D*dieci| r#.ci /* in ci +/-oo
          b-='0'; a+=b| jc .ci
          a&0x80000000 | jnz .ci
          ++i; #.c6;
.ci: a=0x7FFFFFFF;
.c7: ++i; bl=*i; bl>'9'#.c8;
                   bl<'0'#.c8; #.c7
.c8: c#.c9; neg a
.c9: r=@pos; *r=i;
.cf:
>> @string, @pos
> b, c, r, i
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:
{< k
 k = s;
 pushad /* sono necessari perche messagebox sembra cambi anche
ecx!!!
 s-=128;
 << @Title=[k+8], @n=[k+12], @string=[s]
/*--------------------*/
   a=@n; c= & @string; utoa(c, a);
   a=@Title; c= & @string;
   *MessageBoxA( 0, a, c, _ MB_OK || MB_SYSTEMMODAL _ );
>> @Title, @n, @string
 s+=128
 popad
 s = k
> k;
 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:
{< b, r, i, j, k
 << @string=[s+24], @n=[s+28]
/*--------------------*/
 i=@string; b=10; a=@n; j=i; k=0;
 .utoaz_l:
        {r ^= r
         div b /* a= (r:a)/b r= (r:a)%b
         rl+='0'; *j=rl; ++j; ++k
         a#.utoaz_l
        }
  B*j=0; --j | #.vai
  .utoaz_f:
      {al=*i; ah=*j;
       *j=al; *i=ah;
        ++i | --j;
      .vai:
       i<j #.utoaz_f
      }
 a=k;
 .utoaz_z:
>> @string, @n
> b, r, i, j, k
 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:
{< b, r, i, j, k
 << @string=[s+24], @n=[s+28]
/*--------------------*/
     i=@string; b=10; a=@n; k=0;
     a&0x80000000; jz .c0;
          neg a; B*i='-'; #.c1 /* a&0x70000000;
.c0: B*i='+';
.c1: ++i; ++k; j=i;
 .itoaz_l:
        {r ^= r
         div b /* a= (r:a)/b r= (r:a)%b
         rl+='0'; *j=rl; ++j; ++k
         a#.itoaz_l
        }
  B*j=0; --j | #.vai
  .itoaz_f:
      {al=*i; ah=*j;
       *j=al; *i=ah;
        ++i | --j;
      .vai:
       i<j #.itoaz_f
      }
 a=k;
 .itoaz_z:
>> @string, @n
> b, r, i, j, k
 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:
{< a, c, b, i
 << @n=[s+24], @Title=[s+20]
     b=@n; c=@Title; i=c; i+=7;
    .l0:
       {al=bl; al&=0Fh; al+='0';
        al>'9'!#.l1; al+= 7;
       .l1:
        B*i=al; --i; b>>=4; c<=i#.l0
       }
>> @n, @Title
> a, c, b, i
 ret 8
}

Tprinth:
< b, a
  fstp T*num_temp /* il valore in st0 e levato dallo stack
  b=buffer;
  utoh(b, D*num_temp ); b+=8; B*b='#'; ++b /* 32
  utoh(b, D[num_temp+4]); b+=8; B*b='#'; ++b /* +32
  utoh(b, D[num_temp+8]); b+=8; B*b='#'; ++b; B*b='#'; ++b /* +16
  B*b=0; ++b;
  *MessageBoxA( 0, buffer, titolo, _ MB_OK || MB_SYSTEMMODAL _ );
> b, a
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:
{< k
 k = s;
 pushad /* sono necessari perche messagebox sembra cambi anche ecx!!!
 s-=128;
 << @Title=[k+8], @n=[k+12], @HexprintString=[s]
/*--------------------*/
     a=@n; c= & @HexprintString; utoh(c, a);
     a=@Title; c= & @HexprintString;
     *MessageBoxA( 0, c, a, _ MB_OK || MB_SYSTEMMODAL _ );
>> @Title, @n, @HexprintString
 s+=128
 popad
 s = k
> k;
 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:
{< k
   k = s;
< b, c, r, i, j
     s-=16 /* s=0num0, 4num1, 8sign, 12cw_save
     fnstcw [s+12];
     fldcw [cw_data]; /* resetta tutto + troncamento
 /* converti scrive nello 2 dd nello stack qui allocato
     i=[k+8]; converti(); jnc .a0
            a=[k+8]; b=[k+12]; *b=a; fldz; ##.cx
.a0: [s+8]=b; a=0; /* caso non errore
     #.c1 /* leva gli spazi
.c0: ++j| .c1: B*j==' '#.c0;
     bl=B*j;
     bl=='e' #.c2 /* 44.44 e -12455
     bl!='E' #.c3
.c2: converti_exp(); /* in a esponente
     a> 4931 ?#.ce_piu_oo
     c> 4931 ?#.ce_piu_oo
     a< -4931 ?#.ce_zero
.c3: a+=c
     /* uPrint(titolo, a);
     a> 4931 ?#.ce_piu_oo
     a< -4931 ?#.ce_zero
     #.c4
.ce_piu_oo: D[s+8]==0!#.seielmeno |fld T*piu_oo |##.cq;
.seielmeno: fld T*meno_oo; ##.cq;
.ce_zero: fldz; ##.cf;
 .c4: fpow10i(); /* 10^a
    /fist D*nim; uPrint(titolo, D*nim);

.c5: fild Q[s]; /* num, 10^a
    /fist D*nim; uPrint(titolo, D*nim);

     fmulp st1 /* num*10^a
.cf: D[s+8]==0 #.cq; FCHS;
.cq: a=[k+12]; *a=j;
.cx: fldcw [s+12];
     s+=16
> b, c, r, i, j
 s = k
> k;
ret 8

/* <j>pos <a>num+sign converti_exp<j>
converti_exp:
< b, c, r, i, k
     i=j; b=0; r=0;
.c0: ++j| B*j==' ' #.c0; /* leva gli spazi
     B*j=='+'!#.c1 | ++j; #.c2
.c1: B*j=='-'!#.c2 | ++j; ++b;
.c2: B*j>'9' #.ce
     B*j<'0' #.ce /* nel caso dopo eventuale + o -
     #.c3
.ce: j=i; a=0; ##.cf
.c3: #.c5 /* leva gli zeri
.c4: ++j| .c5: B*j=='0' #.c4;
     a=0; c=0; k=0;
.c6: cl=*j
     cl<='9' !#.c8
       cl>='0' !#.c8
          mul D*dieci;
          cl-='0'; a+=c;
          a>4931#.ck
          ++j | #.c6;
.ck: ++j; cl=*j
     cl<='9' !#.c8
       cl>='0' !#.c8 | #.ck
.c8: b==1!#.cf | neg a
.cf:
> b, c, r, i, k
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:
< a, b, c
      a< -4931 ?#.ze
      a> 4931 ?#.oo
      #.c0
 .ze: fldz; ##.fine
 .oo: fld T*piu_oo; ##.fine
 .c0: b=0; a&0x80000000 | jz .c1 | neg a | b=1
 .c1: c=a; c&=0xF; c= &[c+4*c]; c= &[2*c];
      FLD T[dieci_1 + c];
      c=a; c>>= 4; c&=0xF; c= &[c+4*c]; c= &[2*c];
      FLD T[dieci_16 + c];
      c=a; c>>= 8; FMULP st1; /* ok poiche' c<=4931
      c= &[c+4*c]; c= &[2*c]; /* e 4931>>8 == 19
      FLD T[dieci_256 + c];
      b<>1; FMULP st1; jnz .fine
             FLD1 | FDIVRP st1
.fine:
> a, b, c
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:
< a, i, r, k /* i punta sempre al carattere
                  /* corrente della stringa
<< @sign=[s]
     s-=4
     #.c1 /* leva gli spazi
.c0: ++i| .c1: B*i==' ' #.c0;
     D @sign=0;
     B*i=='+' !#.b0 | ++i; #.c2
.b0: B*i=='-' !#.c2 | ++i; ++D @sign;
.c2: B*i>'9' #.ce
     B*i<'0' #.ce /* nel caso dopo eventuale + o -
     #.b1; /* c'e' un non numero => errore
.ce: r=0; a=0; c=0; b=0; j=^12; ##.cf
.b1: #.g1 /* leva gli zeri
.g0: ++i| .g1: B*i=='0' #.g0;
     a=0; r=0; k=0; j=0; c=0;
.c3: al=*i /* prende parte non esponente
     al<='9' !#.c4
        al>='0' !#.c4
          _mult10(); jc .c7
          al-='0'; k+=a | jnc .b2| ++r | jno .b2
                       k-=a; --r; --c #.c7
     .b2: ++i| #.c3;
.c4: al=='.' #.a1 | ##.c9;
.a1: B[i+1]>'9'#.a2 | B[i+1]<'0'#.a2
     #.a3
.a2: ##.c9; /* caso numero.?non_numero
.a3: j=i; /* caso numero.?numero
.ca: ++j; al=*j /* elimina gli zeri superflui
     al>'9'#.cb;
        al<'0'#.cb;
                #.ca;
.cb: --j; al=*j | al=='0'#.cb /* j punta *all'ultimo numero* non zero
     i==j!#.cd; ##.c9 /* tranne caso numero.000000000
.cd: i==j#.a0
         ++i; al=*i;
         _mult10(); jc .a0 /* elimina i restanti decimali
         al-='0'; --c; k+=a | jnc .a4; ++r | jno .a4
                     k-=a; --r; #.a0
    .a4: #.cd;

.c7: ++c; ++i; al=*i /* caso 999etc
     al<='9' !#.c8
         al>='0' #.c7
.c8: al=='.' !#.c9 /* caso 999etc.etc
     B[i+1]>'9'#.c9;
     B[i+1]<'0'#.c9;
    .a0: ++i; al=*i
         al<='9' !#.c9
           al>='0' #.a0
.c9: j=i; b=@sign;
.cf: s+=4
     j==[s+8] !#.cc | stc | #.cz
.cc: clc /* [s+8]==i
.cz: [s+20]=k; [s+24]=r; /* nello stack la risposta
>> @sign
> a, i, r, k
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:
{< a, b, c, i, j
/*------------------*/
     c=r; j=k; a=k; /* salva input in c:j
     mul D*dieci; /* k*10
     i=a; k=r; /* save result in i:k

     a=c; mul D*dieci;
     a+=k | jnc .m0 | ++r;
    .m0:
     r!=0 #.mfineset;
     r=a; k=i;
     r&0x80000000|jnz .mfineset
         /* qui perde un bit per il segno
     clc; #.mfine
    .mfineset:
     r=c; k=j;
     stc;
    .mfine:
> a, b, c, i, j
 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:
< k
  k = s
< b, c, r, i
s-=32 /* 10, 20; 0-9=num, 12-15=exp, 16-17=wc_temp 20-29=bcd
<< @string=[k+8], @exp=[s+12], @wc_temp=[s+16], @bcd=[s+20]
     fnstcw @wc_temp;
     D[s+8]=0;
     fldcw [cw_data]; /* resetta tutto + troncamento
     fxam /* controlla numero in st0 setta c0, c1, c2, c3
     i=@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
     al=ah;
     al & 00000010b | jz .c0 | B*i='-' | #.c1
.c0: B*i='+'
.c1: ++i; al&=01000101b /* leva il bit del segno
     al==00000000b!#.c2 /* in .cf nessuna operazione in fpu-stack
       --i; D*i='Ns'; a=2; ##.cf
.c2: al==00000001b!#.c3
       --i; D*i='NaN'; a=3; ##.cf
.c3: al==00000101b!#.c4
            D*i='InF'; a=4; ##.cf
.c4: al==01000000b!#.c5
            D*i='0.0'; a=4; ##.cf
.c5: al==01000001b!#.c7
       --i; D*i='Nul'; a=3; ##.cf
.c6: D*i='0.0'; a=4; ##.ca
.c7: fld st0; /* st = num, num
     fstp T*s; /* 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 D @exp; /* st = vuoto; salva x in 10^x, pop;
                     /* salva l'esponente
     a = @exp; neg a; a+=17; a>4931?#.c6; /* in .c6 0.0
                     /* 1/10^x * 10^17 = 10^(17-x)=10^a
     call fpow10i; /* st = 10^a
     fld T*s; /* st = num,10^a
     fmulp st1; /* st = num*10^a
     fbstp T @bcd; /* st = vuoto; numero in memoria
  /* ^^^^^^^^^^^^^^^^ salva numero in @bcd=[s+20] *come bcd*
  /* ---------------- scrive nella stringa
     a= & @bcd; b=@exp;
     BcdToString( i, a, b, D[k+12], D[k+16] );
  /* ---------------- ripristino
.ca: fld T*s; /* ricarica il numero nello fpu-stack
                     /* st = num
.cf: fldcw @wc_temp;
>> @string, @exp, @wc_temp, @bcd
s+=32
> b, c, r, i
  s = k
> k;
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:
< k ; k = s ;< b, c, r, i, j; s-=64
<< @string=[k+8], @bcd_number=[k+12], @exp=[k+16], @IntN=[k+20],
@DecN=[k+24]
     j=s; i=@bcd_number; b=@exp; r=i; i+=8;
     B*j='0'; ++j; /* serve per eventuale arrotondamento
     al=*i; cl=*i; cl&=0xf; al>>=4; al+='0'; cl+='0';
     al=='0'!#.c0
          *j=cl; ++j; --i; #.c1
.c0: *j=al; ++b; [j+1]=cl; --i; j+=2;
.c1: al=*i; cl=*i; cl&=0xf; al>>=4; al+='0'; cl+='0';
                     *j=al; ++j; *j=cl; --i; ++j; i>=r#.c1;
     B*j=0; /* ora in s[0..17]"0num" il numero di bcd
     a=@IntN; a==0#.c2
     ##.c4
     
.c2: b<=17 !#.c3 /* b=exp=2<17 c=2, r=15
       b==0 #.c3 /* c=1..17
            r=@DecN; c=b; #.c5;
.c3: c=1; r=@DecN; #.c5;
                        /* b=exp, c=IntN, r=DecN
.c4: c=@IntN; r=@DecN;
.c5: c<17#.c6 | c=17;
.c6: a=17; a-=c; /* a=17-IntN
     r<a #.c7 | r= a;
.c7: i=s; j=&[s+32];
     b-=c; /* i=s b==exp
   
/* nota: c->1..17 r->17-c=0..16
/* arrotonda l'array in s nella cifra scelta
     a=r; a+=c; a==17#.c8; /* nessun arrotondamento
     round(j, i, a, 5); i=j;
/* posiziona il punto nell'array
.c8: j=@string;

.cm: B*i=='0'!#.cn /* puo' essere 0000num in un bcd?
            ++i; #.cm
.cn: B*i<'0'#.co; B*i>'9'#.co
     #.c9
.co: D*j='0.0'; j+=3; #.cc

.c9: al=*i; *j=al; al==0#.cb; ++i,j; --c#.c9
     B*i==0 #.cb;
     r==0 #.cb; /* c=17: fine
     B*j='.'; ++j;
.ca: al=*i; *j=al; al==0#.cb; ++i,j; --r#.ca
.cb: b==0#.cc
        B*j='e'; ++j;
        itoa(j, b); j+=a;
.cc: B*j=0;
     a=@string; j-=a; a=j; ++a;
>> @string, @bcd_number, @exp, @IntN, @DecN
s+=64; > b, c, r, i, j; s = k ; > k;
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:
< k ; k = s ; < b, c, i, j
<< @array=[k+8], @origin=[k+12], @decimal=[k+16], @min=[k+20]
/*-----------------------------------
     i=@origin; j=@array; b=@decimal; c=@min; ++b;
     c>9#.ce; c<0#.ce; b<=1?#.ce; j==0#.ce; i==0#.ce; ##.c0
.ce: a=0; ##.cf;
.c0: cl+='0'; i+=b; j+=b;
     *i>cl!#.c1
       --b;
       IncArray( D @array, D @origin, b); a=b; ++a; #.cf
.c1: *i<cl #.co
.c2: *i==cl!#.c3
         ++i; #.c2
.c3: B*i>'9'#.co; B*i<'0'#.co; *i<=cl#.co;
       --b;
       IncArray( D @array, D @origin, b); a=b; ++a; #.cf
.co: i=@origin; j=@array;
.c4: al=*i; *j=al;
        ++i; ++j; --b#.c4;
     B*j=0;
     a=@array; j-=a; a=j; ++a;
.cf:
>> @array, @origin, @decimal, @min
> b, c, i, j ; s = k ; > k;
ret 16

/* al:ah char IncNum<al>
IncNum:
     al=='9'!#.c0
        al='0'; ah=1; #.cf;
.c0: ++al; 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:
< a, c, i, j
<< @string=[s+20], @origin=[s+24], @pos=[s+28]
/*-------------------------------------
     a=@pos; j=@string; i=@origin; j+=a; i+=a; c=j; ah=1;
   .c0: al=*i; al<'0'#.ce; al>'9'#.ce
        ah==0#.c1 | IncNum();
   .c1: *j=al; j==@string#.ce; --j; --i; #.c0;
.ce: ++c; B*c=0;
>> @string, @origin, @pos
> a, c, i, j
ret 12

ret



Relevant Pages

  • Re: AltairZ80 simulator updated
    ... programming is no longer taught. ... 1000 evcod equ $ ... 1030 evco1 mov a,m ... 1120 ret ...
    (comp.os.cpm)
  • Re: example in nasm
    ... > ret 4 ... WM_PAINT equ 0fh; ... utoaz(.titolo, a); ... *GetClientRect(D*WindowHandle, RECT); ...
    (alt.lang.asm)
  • Re: UltraDOS
    ... AAP EQU 40B1H ... RET Z ... Vernon Hester wrote UltraDOS and sold it through Level IV Products. ...
    (comp.sys.tandy)
  • Re: UltraDOS
    ... AAP EQU 40B1H ... RET Z ... They also sold programming utilities ...
    (comp.sys.tandy)
  • Re: DIM vs. Dynamic
    ... EQU HOL.DATES TO 1 ... LOCATE HOLIDAY.DATE IN HOLIDAYS< HOL.DATES, ... everything's a string. ... They insisted on typing variables with single-char prefixes that were ...
    (comp.databases.pick)