Author Topic: Six Fast Steps to Programming in High Level Assembly (HLA) ...  (Read 47238 times)

Offline David

  • Hero Member
  • *****
  • Posts: 647
    • View Profile
Re: Six Fast Steps to Programming in High Level Assembly (HLA) ...
« Reply #15 on: August 07, 2012, 12:01:40 PM »
Now here is the above Contact program, but using a SLList ...

Code: [Select]
program ContactsSLList2; // 2012-09-03 // testing sllist2.hhf & sllist2_func's.hhf

#includeOnce( "readLine.hhf" )
#includeOnce( "sllist2_func's.hhf" ) // also has includes sllist2.hhf

// NOTE that ALSO set by above include sslist2.hhf ... ? @nodisplay:= true;
// So ... all procedures have @nodisplay 'as default' from here on ...


const   
    FNAME: text := """contacts.dat"""; // each """ includes one " in output
   
static
    // global variables utilized in program (to keep it simple here)
    Sorted:     boolean := false;
    Done:       boolean := false;
    Update:     boolean := false;

type
    MyContact: record
                    theName:    string;
                    thePhone:   string;
                endrecord;
               
static
    myBook: SLList; // SLList type was defined above in included file "sllist2.hhf"


procedure destroyMyC( p: dword in eax ); @noframe;
begin destroyMyC;
    push( ebx );
    mov( [eax], ebx );
    str.free( (type MyContact [ebx]).theName );
    str.free( (type MyContact [ebx]).thePhone );
    mem.free( ebx );
    pop( ebx );
    ret();
end destroyMyC;

// for isort/msort... by names ...
procedure myCmp( a: dword in esi; b: dword in edi ); @returns("eax");
begin myCmp;
    push( ebx );
    mov( [esi], eax );
    mov( [edi], ebx );
    if(  str.le( (type MyContact [eax]).theName,
                    (type MyContact [ebx]).theName ) ) then
        mov( 1, eax );
    else
        mov( 0, eax );
    endif;
    pop( ebx );
end myCmp;

// for find by name ...
procedure myCmpEQ( a: dword in esi; b: dword in edi ); @returns("eax");
begin myCmpEQ;
    push( ebx );
    mov( [esi], eax );
    mov( [edi], ebx );
    if(  str.eq( (type MyContact [eax]).theName,
                    (type MyContact [ebx]).theName ) ) then
        mov( 1, eax );
    else
        mov( 0, eax );
    endif;
    pop( ebx );
end myCmpEQ;

// returns string 'taken in' in eax ...
procedure takeIn( message:string; value:string ); @returns("eax");
begin takeIn;
    push( edi );
    forever;
        stdout.puts( message );
        if( str.length( value ) > 0 ) then
            stdout.put( "(", value, "): " );
        else
            stdout.puts( ": " );
        endif;

        stdin.flushInput();
        stdin.a_gets();
        mov( eax, edi );
        // ensure first letter is Upper Case ...
        mov( mov( chars.toUpper( [edi] ), al), (type char [edi]) );

        stdout.put("You input '", (type string edi), "'  Ok (y/n) ? " );
        stdin.getc();
        chars.toLower( al );
        if( al == 'y' ) then
            mov( edi, eax );
            break;
        else
            str.free( edi );
        endif;
    endfor;
    pop( edi );
end takeIn;



procedure fileBook( var sll: SLList );
var
    fout:   dword;
begin fileBook;
    push( eax ); push( ebx );

    try

        fileio.openNew( FNAME ); // overwrites any existing file
        mov( eax, fout );
        mov( sll, eax );
        mov( (type SLList [eax]).head, eax );
        while( eax ) do
            mov( [eax], ebx );
            fileio.put( fout, (type MyContact [ebx]).theName, nl );
            fileio.put( fout, (type MyContact [ebx]).thePhone, nl );
            mov( (type NNode[eax]).next, eax );
        endwhile;
        fileio.close( fout );

        exception( ex.FileOpenFailure )
        stdout.put( "There was a problem opening file ",  FNAME,
                    " for output." nl );
    endtry;

    pop( ebx ); pop( eax );
end fileBook;


// Total number of contacts is stored in global variable RecCount
procedure addContacts( var sll: SLList );
var
    newNNode:   NNode;
    oldSize:    uns32;
begin addContacts;
    push( eax ); push( ebx ); push( ecx );

    mov( sll, ebx );
    mov( (type SLList [ebx]).size, eax );
    mov( eax, oldSize );
    mov( (type SLList [ebx]).head, eax );

    stdout.puts( "To abort/exit, just enter/accept an empty line "
                 "for 'name' or 'phone' ... " nl );
    forever
        mem.alloc( @size( MyContact ) );
        mov( eax, ecx );
        mov( takeIn( "Enter name   ", "" ), (type MyContact [ecx]).theName );
        mov( takeIn( "Enter phone  ", "" ), (type MyContact [ecx]).thePhone );
        if( str.length( (type MyContact [ecx]).theName ) &&
            str.length( (type MyContact [ecx]).thePhone ) ) then
            mov( ecx, newNNode.nval );   
            push_backSLList( (type SLList [ebx]), newNNode );
        else
            str.free( (type MyContact [ecx]).thePhone );
            str.free( (type MyContact [ecx]).theName );
            stdout.puts( "Ok ... aborted ... " );
        endif;
           
        stdout.puts( nl "More y/n ? " );
        stdin.flushInput();
        stdin.getc();
        chars.toLower( al );
        breakif( al == 'n' );
    endfor;

    mov( (type SLList [ebx]).size, ecx );
    if( ecx > oldSize ) then    // Contacts were added ...
        mov( &myCmp, pMyCmp ); // so can msort... ok, when called ...
        msortSLList( (type SLList [ebx]) ); // also updates Update
        mov( true, Sorted );
        mov( true, Update );
    endif;

    pop( ecx ); pop( ebx); pop( eax );
end addContacts;


// returns count of records in file in SLList size parameter
procedure inputBook_fromFile( var sll: SLList );
var
    fin:        dword;
    newNNode:   NNode;
   
begin inputBook_fromFile;
    push( eax ); push( ebx ); push( ecx );

    try
        fileio.open( FNAME, fileio.r ); // open file for reading
        mov( eax, fin );

        mov( sll, ebx );
        while( !fileio.eof( fin) ) do
           
            mem.alloc( @size( MyContact ) );
            mov( eax, ecx );
           
            // allocate space for new string and
            // mov pointer into array (of pointers)
            fileio.a_gets( fin );     // returns new string in eax
            mov( eax, (type MyContact [ecx]).theName ); // get Contact
            fileio.a_gets( fin);
            mov( eax, (type MyContact [ecx]).thePhone );
            mov( ecx, newNNode.nval );
            push_backSLList( (type SLList [ebx]), newNNode );

        endwhile;
        fileio.close( fin );

    exception( ex.FileOpenFailure )

        stdout.puts
        (
            nl "There was some problem reading your file. " 
            "Perhaps it dosen't exist?"
            nl "Do want to start a new contact book (y/n) ? "
        );
        stdin.getc();
        chars.toLower( al );
        if( al == 'y' ) then
            mov( sll, ebx );
            addContacts( (type SLList [ebx]) );   
        endif;

    endtry;

    pop( ecx ); pop( ebx ); pop( eax );   
end inputBook_fromFile;


procedure editContact( var sll: SLList; pn: dword in eax );
var
    s:      string;
begin editContact;
    push( ebx ); push( ecx ); push( edx );
   
    mov( sll, ebx );
    if( (type SLList [ebx]).size > 0 ) then // need at least 1 record to edit
       
        // free old allocated strings and overwite with new ... (if updated )
       
        mov( [eax], ecx ); // derefence pointer
        mov( (type MyContact [ecx]).theName, edx );
        mov( edx, s ); // get copy of pointer into s ...
        stdout.puts( "To abort/exit, just enter/accept an empty "
                        "line for a name ... " nl );
        mov( takeIn( "Enter name   ", s ), (type MyContact [ecx]).theName );
        if( str.length( (type MyContact [ecx]).theName ) ) then // if NOT empty ...
            str.free( s );
           
            mov( (type MyContact [ecx]).thePhone, edx );
            mov( edx, s ); // get copy into s ...
            mov( takeIn( "Enter phone  ", s ),  (type MyContact [ecx]).thePhone );
            str.free( s );
           
            mov( &myCmp, pMyCmp ); // so can msort ok, when called ...
            msortSLList( (type SLList [ebx]) ); // also updates Update ...
            mov( true, Sorted );
            mov( true, Update );
        else
            str.free( (type MyContact [ecx]).theName ); // free rejected entry ...
            mov( mov( s, edx ), (type MyContact [ecx]).theName ); // restore original
            stdout.puts( "Ok ... edit aborted ... " nl );
        endif;
       
    endif;
   
    pop( edx ); pop( ecx ); pop( ebx );
end editContact;


procedure showBook( var sll: SLList ); 
var
    lineCount:  int32;
begin showBook;
    push( eax ); push( ebx ); push( ecx ); push( edx );

    // a little different formatting ...
    console.cls();
    stdout.puts
    (
        nl "Your 'book'  :  __________________________________________________" nl
    );

    mov( 2, lineCount );

    mov( sll, ebx );
    mov( (type SLList [ebx]).head, eax );
    mov( 0, ecx );
    while( eax ) do

        inc( lineCount );
       
        stdout.puts( nl stdio.tab stdio.tab );

        inc( ecx ); // to show 1,2,3 ... and not 0,1,2 ...
        stdout.putu32Size( ecx, 3, '0' );
       
        mov( [eax], edx );
        stdout.put( ": ", (type MyContact [edx]).theName : -24 );
        stdout.puts( " ---> " );
        stdout.put( (type MyContact [edx]).thePhone : 15 );
       
        mov( (type NNode [eax]).next, eax );

    endwhile;

    pop( edx ); pop( ecx ); pop( ebx ); pop( eax );
end showBook;




procedure showMenu( var sll: SLList );
var
    s:          string;
    oldSize:    uns32;
    myC:        MyContact;
    myNNode:    NNode;
begin showMenu;
    push( eax ); push( ebx );

    mov( sll, ebx );
    showBook( (type SLList [ebx]) );
    stdout.put
    (
        nl nl "Total contacts now in memory = ", (type SLList [ebx]).size,
        nl nl "Add, Delete, Edit, Sort, XDuplicates or Quit (a, d, e, s, x, q) ? "
    );
    stdin.flushInput();
    stdin.getc();
    chars.toLower( al );
   
    if( al == 'a' ) then
        addContacts( (type SLList [ebx]) );
       
    elseif( al == 'd' ) then

        stdout.puts( "To abort/exit, just enter/accept an empty "
                        "line for a name ... " nl );
        mov( takeIn( "Enter name to find", "" ),
                        myC.theName ); // returns in eax then copies pointer to myC.string
           
        if( str.length( myC.theName ) ) then
            mov( &myCmpEQ, pMyCmp );            // so can use findVec (EQ)
            findSLList( (type SLList [ebx]), myC ); // returns pointer or 0
            if( eax ) then
                stdout.put( "Found ... so erasing ... " nl );
                mov( &destroyMyC, pFreeNNode );
                eraseSLList( (type SLList [ebx]), eax ); // a library proc
            else
                stdout.put( myC.theName, " was NOT found ... " nl );
                str.free( myC.theName );
            endif;
           
        else
            str.free( myC.theName );
            stdout.puts( "Ok ... aborting delete ... " nl );
        endif; 
       
        stdout.put( nl "Press 'Enter' to continue ... " );
        stdin.readLn();
           
    elseif( al == 'e' ) then
   
        mem.alloc( @size( MyContact ) );
        mov( eax, ecx );
   
        stdout.puts( "To abort/exit, just enter/accept an empty "
                        "line for a name ... " nl );
        mov( takeIn( "Enter name to find", "" ), // returns in eax then copies pointer ...
                        (type MyContact [ecx]).theName );
           
        if( str.length( (type MyContact [ecx]).theName ) ) then
            mov( &myCmpEQ, pMyCmp );            // so can use findSLList (EQ)
            mov( ecx, myNNode.nval );
            findSLList( (type SLList [ebx]), myNNode ); // returns pointer or 0
           
            if( eax )  then
                stdout.put( "Found ... ", nl );
                editContact( (type SLList [ebx]), eax ); 
            else
                stdout.put( myC.theName, " was NOT found ... " nl );
                str.free( myC.theName );
            endif;
           
        else
            str.free( myC.theName );
            stdout.puts( "Ok ... aborting edit ... " nl );
        endif;
       
        mem.free( ecx );
        stdout.put( nl "Press 'Enter' to continue ... " );
        stdin.readLn();
   
    elseif( al == 's' ) then
        mov( &myCmp, pMyCmp ); // so can msort... ok, when called
        msortSLList( (type SLList [ebx]) );
        mov( true, Sorted );
        mov( true, Update );
     
    elseif( al == 'x' ) then
   
        if( !Sorted ) then
            mov( &myCmp, pMyCmp ); // so can msort... ok, when called
            msortSLList( (type SLList [ebx]) );
            mov( true, Sorted );
            mov( true, Update );
        endif;
       
        mov( &myCmpEQ, pMyCmp ); // so can cmp (EQ)... ok, when called
        mov( &destroyMyC, pFreeNNode );
        mov( sll, ebx );
        mov( (type SLList [ebx]).size, oldSize );
        uniqueSLList( (type SLList [ebx]) ); // pre-sort array to 'chop' duplicates
     
        mov( (type SLList [ebx]).size, eax );
        if( eax < oldSize ) then
            mov( true, Update );    // and ... will update 'contacts.dat' file
        endif;
       
    elseif( al == 'q' ) then
        mov( true, Done );      // 'Done' is also a global variable
       
    endif;
   
    pop( ebx ); pop( eax );
end showMenu;






begin ContactsSLList2;

    initSLList( myBook );
   
    mov( &destroyMyC, pFreeNNode );
   
    inputBook_fromFile( myBook ); // returns the record count in size parameter
    repeat
        showMenu( myBook );
    until( Done );

    if( Update ) then
        fileBook( myBook );
        stdout.put( nl "Ok ... your BOOK should NOW be filed in file '",
                    FNAME, "' ... " nl );
    endif; // update file if changes ...
   
    stdout.put( nl "Before clear... myBook.size = ", myBook.size, nl );
    clearSLList( myBook );
    stdout.put( "After clear... myBook.size = ", myBook.size, nl );
   
    stdout.put( nl "Press 'Enter' to continue/exit ... " );
    stdin.readLn();

end ContactsSLList2;


You will find the 3 files you need to have available to include ...

"readLine.hhf"

"sllist2_func's.hhf"

"sllist2.hhf"

at this next link:

http://developers-heaven.net/forum/index.php?topic=2600.0
« Last Edit: September 04, 2012, 02:22:11 AM by David »

Offline David

  • Hero Member
  • *****
  • Posts: 647
    • View Profile
Re: Six Fast Steps to Programming in High Level Assembly (HLA) ...
« Reply #16 on: August 07, 2012, 12:04:53 PM »
Oops ... just remember this little demo of using vector2.hhf ... that demo's using two different kinds of programmer defined records in the same program ... using my HLA user defined type Vec (2) container ...

First the two little test data files that I used:

// "testInt.dat"
Code: [Select]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
// "testStr.dat"
Code: [Select]

z 3456789 123456789 123456789
2z
32z
444z
5555z
66666z
777z
88z
9z
z


And here is the demo/test file ...

Code: [Select]
program testVec2StrInt; // 2012-09-03 //

#includeOnce( "readWord.hhf" )

const
    Fname:  text := """testStr.dat""" ;
    Fname2: text := """testInt.dat""" ;
    InitCap: uns32 := 2; // Note: if NOT defined here defaults to 8
                        // kept small for testing of Vec memory reallocates
                       
#includeOnce( "vector2_func's.hhf" ); // Note: has #includeOnce("vector2.hhf");
                                      // and "vector2.hhf" has ? @nodisplay:= true;
                                      // so all procedures have @nodisplay 'as default'

 
                     
// Ok ... now we need to define our records ...
// and free rec procedures (to handle potential case of dynamic memory)

type
    Rec:    record
                str:    string;
            endrecord;

procedure freeRec( pr: dword in eax ); @noframe;
begin freeRec;
    str.free( (type Rec [eax]).str );
    ret();
end freeRec;

type
    Rec2:   record
                i32:    int32;
            endrecord;
 
procedure freeRec2( pr: dword in eax ); @noframe;
begin freeRec2;
    // no dynamic memory to free here ...
    ret();
end freeRec2;



// Now ... we can define our compare functions to be used by find and sort ...

// re. isort...
procedure myCmp( a: dword in esi; b: dword in edi ); @returns("eax");
begin myCmp;
    if(  str.lt( (type Rec [esi]).str, (type Rec [edi]).str ) ) then mov( 1, eax );
    else mov( 0, eax );
    endif;
end myCmp;

// re. msort...
procedure myCmpLE( a: dword in esi; b: dword in edi ); @returns("eax");
begin myCmpLE;
    if(  str.le( (type Rec [esi]).str, (type Rec [edi]).str ) ) then mov( 1, eax );
    else mov( 0, eax );
    endif;
end myCmpLE;

// re. isort...
procedure myCmpRev( a: dword in esi; b: dword in edi );  @returns("eax");
begin myCmpRev;
    if(  str.gt( (type Rec [esi]).str, (type Rec [edi]).str ) ) then mov( 1, eax );
    else mov( 0, eax );
    endif;
end myCmpRev;

// re. find...
procedure myCmpEQ( a: dword in esi; b: dword in edi );  @returns("eax");
begin myCmpEQ;
    if(  str.eq( (type Rec [esi]).str, (type Rec [edi]).str ) ) then mov( 1, eax );
    else mov( 0, eax );
    endif;
end myCmpEQ;


// re. comparing int32 ... for msort reverse order... recall >=  is used
procedure myCmpIntRev( a: dword in esi; b: dword in edi );  @returns("eax");
begin myCmpIntRev;
    mov( (type Rec2 [esi]).i32, esi );
    mov( (type Rec2 [edi]).i32, eax );
    if( (type int32 esi) >= eax ) then mov( 1, eax ); // i.e. descending sort
    else mov( 0, eax );
    endif;
end myCmpIntRev;

// re. find int32...
procedure myCmpEQRec2( a: dword in esi; b: dword in edi );  @returns("eax");
begin myCmpEQRec2;
    mov( (type Rec2 [esi]).i32, esi );
    mov( (type Rec2 [edi]).i32, eax );
    if( (type int32 esi) == eax ) then mov( 1, eax );
    else mov( 0, eax );
    endif;
end myCmpEQRec2;



// so can reuse showVec with different showRec's ...
static
    pShowRec: procedure(  pr: dword in eax ); // get a proc pointer
   
 
// Now .. define show record ... for each different record  ...

procedure showRec( pr: dword in eax ); @noframe;
begin showRec;
    stdout.puts( (type Rec [eax]).str );
    ret();
end showRec;

procedure showRec2( pr: dword in eax ); @noframe;
begin showRec2;
    stdout.puti32( [eax] );
    ret();
end showRec2;       
 

// using above procedure pointer pShowRec ... can define showVec
         
procedure showVec( var v: Vec );
begin showVec;
    push( eax ); push( ebx ); push( ecx );
   
    mov( v, ebx );
    for( mov( 0, ecx ); ecx < (type Vec[ebx]).size; inc( ecx ) ) do
   
        mov( ecx, eax );
        intmul( (type Vec [ebx]).elen, eax );
        add( (type Vec[ebx]).ary, eax );
        pShowRec( eax );
        stdout.putc( ' ' );
       
    endfor;
 
    pop( ecx ); pop( ebx ); pop( eax );
end showVec;

   
   
static
    fin:    dword;  // file handle
   
    myRec:  Rec;    // get some objects with memory ...   
    myRec2: Rec2;
    myVec:  Vec;
    myVec2: Vec;
   
    tmpStr: string;

   
   
begin testVec2StrInt;

    // get some strings from file into a Vec using push_backVec...
   
    fileio.open( Fname, fileio.r );
    mov( eax, fin );
    initVec( myVec, @size(Rec) );   // Note: must initial for Vec to work
   
    while( readWord( fin, myRec.str, " " nl stdio.tab ) ) do
        push_backVec( myVec, &myRec ); // Note here, passing Vec by ref and Rec by pointer
    endwhile;
   
    fileio.close( fin );
   
    stdout.puts( "Showing vec of str ... " nl  );
   
    mov( &showRec, pShowRec );
    showVec( myVec );
    stdout.put( "size = ", myVec.size, ", capacity = ", myVec.capacity, nl );
   
    mov( &myCmp, pMyCmp );
    isortVec( myVec );
   
    stdout.puts( nl "Showing insert sorted vec of str ... " nl  );
    showVec( myVec );
    stdout.put( "size = ", myVec.size, ", capacity = ", myVec.capacity, nl )

    mov( &myCmpRev, pMyCmp );
    isortVec( myVec );
   
    stdout.puts( nl "Showing insert sorted REVERSE vec of str ... " nl  );
    showVec( myVec );
    stdout.put( "size = ", myVec.size, ", capacity = ", myVec.capacity, nl );


    mov( &myCmpLE, pMyCmp );
    msortVec( myVec );
   
    stdout.puts( nl "Showing merge sorted vec of str ... " nl  );
    showVec( myVec );
    stdout.put( "size = ", myVec.size, ", capacity = ", myVec.capacity, nl nl );
   
    str.a_cpy( "777z" );
    mov( eax, myRec.str );
   
    mov( &myCmpEQ, pMyCmp );
    findVec( myVec, &myRec );
   
    mov( &freeRec, pFreeRec );
    if( (type int32 eax) != -1 ) then
        stdout.put( "'", myRec.str, "' WAS FOUND at index ", (type int32 eax), nl );
        stdout.puts( "So after erasing ...  vec is ... " nl );
        eraseVec( myVec, eax );
        showVec( myVec );
    else
        stdout.put( "'", myRec.str, "' was NOT found in the vector ... ", nl );
    endif;
   
    // ok ... clean up all dynamic memory when 'done'
    str.free( myRec.str );
   
    //mov( &freeRec, pFreeRec ); // done above before erase ...
    clearVec( myVec );
   
   
    stdout.puts( nl "Press 'Enter' to continue to Vec of integers from file  ... " );
    stdin.readLn();
   
   
   
    // get some int's from an int file into a different Vec (using push_backVec...)
   
   
    fileio.open( Fname2, fileio.r );
    mov( eax, fin );
    initVec( myVec2, @size(Rec2) );
   
    while( readWord( fin, tmpStr, " " nl stdio.tab ) ) do
        conv.strToi32( tmpStr, 0 ); // begin at index 0 ...
        mov( eax, myRec2.i32 );
        push_backVec( myVec2, &myRec2 );
    endwhile;
   
    fileio.close( fin );
   
    stdout.puts( "Showing vec of int32 ... " nl  );
   
    mov( &showRec2, pShowRec );
    showVec( myVec2 );
    stdout.put( "size = ", myVec2.size, ", capacity = ", myVec2.capacity, nl );
   
    mov( &myCmpIntRev, pMyCmp );
    msortVec( myVec2 );
   
    stdout.puts( nl "Showing merge sorted (reverse) vec of int32 ... " nl  );
    showVec( myVec2 );
    stdout.put( "size = ", myVec2.size, ", capacity = ", myVec2.capacity, nl );
   
    mov( 11, myRec2.i32 );
   
    mov( &myCmpEQRec2, pMyCmp );
    findVec( myVec2, &myRec2 );
   
    mov( &freeRec2, pFreeRec );
    if( (type int32 eax) != -1 ) then
        stdout.put( nl "'", myRec2.i32, "' WAS FOUND at index ", (type int32 eax), nl );
        stdout.puts( nl "So after erasing ...  vec is ... " nl );
        eraseVec( myVec2, eax );
        showVec( myVec2 );
    else
        stdout.put( "'", myRec2.i32, "' was NOT found in the vector ... ", nl );
    endif;
   
    stdout.put( "size = ", myVec2.size, ", capacity = ", myVec2.capacity, nl nl );
   
 
    // mov( &freeRec2, pFreeRec ); // done above before erase ...
    clearVec( myVec2 );
   
    stdout.put( "After clear... size = ", myVec2.size, ", capacity = ",
                myVec2.capacity, nl nl );
 
    stdout.puts( nl "Press 'Enter' to continue/exit ... " );
    stdin.readLn();

end testVec2StrInt;


You will find the 3 files you need to have available to include ...

"readWord.hhf"

"vector2_func's.hhf"

"vector2.hhf"

at this next link:

http://developers-heaven.net/forum/index.php?topic=2600.0


Now ... like the above, but using a SLList ...

Code: [Select]
program testSLList2StrInt; // 2012-09-03 //

#includeOnce( "readWord.hhf" )  // Note: has ? @nodisplay:= true; ... so all
                                // procedures have @nodisplay 'as default'

#includeOnce( "sllist2_func's.hhf" ); // Note: has #includeOnce("sllist2.hhf");

const
    Fname:  text := """testStr.dat""" ;
    Fname2: text := """testInt.dat""" ;
                       
                     
// Ok ... now we need to define our records ...
// and free NNode procedures (to handle potential case of dynamic memory)


procedure freeStrNNode( pr: dword in eax ); @noframe;
begin freeStrNNode;
    str.free( (type NNode [eax]).nval );
    ret();
end freeStrNNode;

procedure freeIntNNode( pr: dword in eax ); @noframe;
begin freeIntNNode;
    // no dynamic memory to free here ...
    ret();
end freeIntNNode;



// Now ... we can define our compare functions to be used by find and sort ...


// re. msort/isort...
procedure myCmpLE( a: dword in esi; b: dword in edi ); @returns("eax");
begin myCmpLE;
    if(  str.le( (type NNode [esi]).nval, (type NNode [edi]).nval ) ) then mov( 1, eax );
    else mov( 0, eax );
    endif;
end myCmpLE;

// re. msort/isort...
procedure myCmpRev( a: dword in esi; b: dword in edi );  @returns("eax");
begin myCmpRev;
    if(  str.ge( (type NNode [esi]).nval, (type NNode [edi]).nval ) ) then mov( 1, eax );
    else mov( 0, eax );
    endif;
end myCmpRev;

// re. find...
procedure myCmpEQ( a: dword in esi; b: dword in edi );  @returns("eax");
begin myCmpEQ;
    if(  str.eq( (type NNode [esi]).nval, (type NNode [edi]).nval ) ) then mov( 1, eax );
    else mov( 0, eax );
    endif;
end myCmpEQ;




// re. comparing int32 ... for isort/msort reverse order... recall >=  used
procedure myCmpIntRev( a: dword in esi; b: dword in edi );  @returns("eax");
begin myCmpIntRev;
    mov( (type NNode [esi]).nval, eax );
    if( (type int32 eax) >= (type NNode [edi]).nval ) then mov( 1, eax );
    else mov( 0, eax );
    endif;
end myCmpIntRev;

// for isort/msort ascending ...
procedure myCmpInt( a: dword in esi; b: dword in edi );  @returns("eax");
begin myCmpInt;
    mov( (type NNode [esi]).nval, eax );
    if( (type int32 eax) <= (type NNode [edi]).nval ) then mov( 1, eax );
    else mov( 0, eax );
    endif;
end myCmpInt;

// re. find int32...
procedure myCmpEQInt( a: dword in esi; b: dword in edi );  @returns("eax");
begin myCmpEQInt;
    mov( (type NNode [esi]).nval, eax );
    if( eax == (type NNode [edi]).nval ) then mov( 1, eax );
    else mov( 0, eax );
    endif;
end myCmpEQInt;



// so can reuse showSLList with different showRec's ...
static
    pShowNNode: procedure(  pr: dword in eax ); // get a proc pointer
   
 
// Now .. define show record ... for each different record  ...

procedure showNNodeStr( pr: dword in eax ); @noframe;
begin showNNodeStr;
    stdout.puts( (type NNode [eax]).nval );
    ret();
end showNNodeStr;

procedure showNNodeInt( pr: dword in eax ); @noframe;
begin showNNodeInt;
    stdout.puti32( (type NNode [eax]).nval );
    ret();
end showNNodeInt;       
 

// using above procedure pointer pShowNNode ... can define showSLList
         
procedure showSLList( var v: SLList );
begin showSLList;
    push( eax );
   
    mov( v, eax );
    mov( (type SLList[eax]).head, eax );
    while( eax ) do
   
        pShowNNode( eax );
        mov( (type NNode[eax]).next, eax );
        stdout.putc( ' ' );
       
    endwhile;
 
    pop( eax );
end showSLList;

   
   
static
    fin:        dword;  // file handle
 
    myNNode:    NNode;
    mySLList:   SLList;
    mySLList2:  SLList;
   
    tmpStr:     string;

   
   
begin testSLList2StrInt;

    // get some strings from file into a SLList using push_backSLList...
   
    fileio.open( Fname, fileio.r );
    mov( eax, fin );
    initSLList( mySLList );   // Note: must initial for SLList to work
   
    while( readWord( fin, myNNode.nval, " " nl stdio.tab ) ) do
        push_backSLList( mySLList, myNNode ); // Note here, passing SLList and myNNode by ref
    endwhile;
   
    fileio.close( fin );
   
    stdout.puts( "Showing SLList of string ... " nl  );
   
    mov( &showNNodeStr, pShowNNode );
    showSLList( mySLList );
    stdout.put( "size = ", mySLList.size, nl );
   
    mov( &myCmpLE, pMyCmp );
    isortSLList( mySLList );
   
    stdout.puts( nl "Showing insert sorted SLList of str ... " nl  );
    showSLList( mySLList );
    stdout.put( "size = ", mySLList.size, nl )

    mov( &myCmpRev, pMyCmp );
    isortSLList( mySLList );
   
    stdout.puts( nl "Showing insert sorted REVERSE SLList of str ... " nl  );
    showSLList( mySLList );
    stdout.put( "size = ", mySLList.size, nl );


    mov( &myCmpLE, pMyCmp );
    msortSLList( mySLList );
   
    stdout.puts( nl "Showing merge sorted SLList of str ... " nl  );
    showSLList( mySLList );
    stdout.put( "size = ", mySLList.size, nl nl );
   
   
   
    str.a_cpy( "777z" );
    mov( eax, myNNode.nval );
   
    mov( &myCmpEQ, pMyCmp );
    findSLList( mySLList, myNNode );
   
    mov( &freeStrNNode, pFreeNNode );
    if( eax ) then
        stdout.puts( "Found ... So erasing ... and SLList now is ... " nl );
        eraseSLList( mySLList, eax );
        showSLList( mySLList );
    else
        stdout.put( "'", (type string myNNode.nval), "' was NOT found in the SLList ... ", nl );
    endif;
   
    // ok ... clean up all dynamic memory when 'done'
    str.free( myNNode.nval );
   
    //mov( &freeStrNNode, pFreeNNode ); // done above ...(before erase)
    clearSLList( mySLList );
   
 
    stdout.puts( nl "Press 'Enter' to continue to SLList of integers from file  ... " );
    stdin.readLn();
   
   
   
    // get some int's from an int file into a different SLList (using push_backSLList...)
   
   
    fileio.open( Fname2, fileio.r );
    mov( eax, fin );
    initSLList( mySLList2 );
   
    while( readWord( fin, tmpStr, " " nl stdio.tab ) ) do
        conv.strToi32( tmpStr, 0 ); // begin at index 0 ...
        mov( eax, myNNode.nval );
        push_backSLList( mySLList2, myNNode );
        str.free( tmpStr );
    endwhile;
   
    fileio.close( fin );
   
    stdout.puts( "Showing SLList of int32 ... " nl  );
   
    mov( &showNNodeInt, pShowNNode );
    showSLList( mySLList2 );
    stdout.put( "size = ", mySLList2.size, nl );
   
    mov( &myCmpIntRev, pMyCmp );
    msortSLList( mySLList2 );
   
    stdout.puts( nl "Showing merge sorted (reverse) SLList of int32 ... " nl  );
    showSLList( mySLList2 );
    stdout.put( "size = ", mySLList2.size, nl );
   
    mov( 11, myNNode.nval );
   
    mov( &myCmpEQInt, pMyCmp );
    findSLList( mySLList2, myNNode );
   
    mov( &freeIntNNode, pFreeNNode );
    if( eax ) then
        stdout.put( nl "Found ", (type int32 myNNode.nval),
                        " so after erasing SLList is ... " nl );
        eraseSLList( mySLList2, eax );
        showSLList( mySLList2 );
    else
        stdout.put( "'", (type int32 myNNode.nval), "' was NOT found in the SLList ... ", nl );
    endif;
   
   
    stdout.puts( nl "Showing insert sorted SLList of int32 ... " nl  );
    mov( &myCmpInt, pMyCmp );
    isortSLList( mySLList2 );
    showSLList( mySLList2 );
    stdout.put( "size = ", mySLList2.size, nl );;
   
 
    // mov( &freeIntNNode, pFreeNNode ); // done above before erase ...
    clearSLList( mySLList2 );
   
    stdout.put( "After clear... size = ", mySLList2.size, nl nl );
 
    stdout.puts( nl "Press 'Enter' to continue/exit ... " );
    stdin.readLn();

end testSLList2StrInt;
« Last Edit: September 04, 2012, 02:26:38 AM by David »

Offline David

  • Hero Member
  • *****
  • Posts: 647
    • View Profile
Re: Six Fast Steps to Programming in High Level Assembly (HLA) ...
« Reply #17 on: August 07, 2012, 12:06:07 PM »
Now here is a timed very SLOW read from file ... HLA example ... from a LARGE file of 3,000,000 random integers ...

(See example of the C code version at the bottom of the msortVecInt.hla program file).

Note: USING "vector.hhf" and "vector_func's.hhf' here ... You will first need to create a file of 3,000,000 random integers ... AND MAKE SURE there is NO WHITE SPACE/New line char's at the end of the file after the ending 3,000,000th integer ... (OR the program will CRASH - but not with C coded Cvec version ... and file read in C version was 50 to 90 times faster.) 

Code: [Select]
/* msortVecInt.hla */ /* this version 2012-08-22 */

/*
    NOTE!
   
    FILE READ ERROR if NL char at end of file of integers ...
    SO ... first MUST ensure all non-numeric char's, are trimmed from
    the end of the file of integers  ... can use a text editor !
*/

/*
   http://developers-heaven.net/forum/index.php/topic,46.0.html
*/

program msortVecIntLarge;

const
    InitCap:    uns32   := 3000000; // to hold 3 Million random int's
    HEADER:     string  := "HLA program to sort 3 Million random int's from file"
                            #13 #10 "stored in an HLA user defined type Vec...";

//#includeOnce( "readWord.hhf" )


type
    Rec:    record
                rval:   int32;
            endrecord;
           
    pRec:   pointer to Rec;
   
procedure freeRec( pr: pRec in eax ); @noframe;
begin freeRec;
    // NO dynamic memory here to free ...
    ret();
end freeRec;

// ok ... after above two types defined ... now can ...

#includeOnce( "vector_func's.hhf" )

procedure myCmpInt( a: pRec in esi; b: pRec in edi ); @returns( "eax" );
begin myCmpInt;
    mov( (type Rec [esi]).rval, eax );
    if( eax <= (type Rec [edi]).rval ) then mov( 1, eax );
    else mov( 0, eax );
    endif;
end myCmpInt;

procedure isSorted( var v: Vec ); @returns( "eax" );
begin isSorted;
    mov( v, ebx );
    mov( (type Vec [ebx]).size, ecx );
    dec( ecx );
    intmul( @size( Rec ), ecx, eax );
    add( (type Vec [ebx]).ary, eax );
    mov( (type Rec [eax]).rval, edi );
    while( (type int32 ecx) > 0 ) do
        dec( ecx );
        sub( @size( Rec ), eax );
        mov( (type Rec [eax]).rval, esi );
        if( (type int32 esi) > edi ) then
            mov( 0, eax );
            break;
        endif;
        mov( esi, edi );
    endwhile;
    mov( 1, eax );
end isSorted;




static
    myVec:  Vec;
    myRec:  Rec;
    fin:    dword;
    tmpStr: string;
   
clock:  timer_t;



begin msortVecIntLarge;

    stdout.put( HEADER, nl nl );
   
    initVec( myVec );
   
    clock.create();
    clock.start();
   
    fileio.open( "randInt3M.txt", fileio.r );
    mov( eax, fin );
    while( !fileio.eof( fin ) ) do
        fileio.geti32( fin );
        mov( eax, myRec.rval );
        // push( ebx ); push( ecx ); push( esi ); push( edi ); // if needed //
        push_backVec( myVec, myRec );
    endwhile;
   
    clock.stop();
    stdout.put( nl "To fill Vec from file ... ms = ", (type uns64 clock.Accumulated), nl );
   
    clock.start();
    mov( &myCmpInt, pMyCmp );
    msortVec( myVec );
    clock.stop();
    stdout.put( nl "To msort ... ms = ", (type uns64 clock.Accumulated), nl );
   
    isSorted( myVec );
    stdout.put( "isSorted( myVec ) = ", (type boolean al) );
   
   
    stdout.puts( nl nl "Press 'Enter' to exit/continue ... " );
    stdin.readLn();

end msortVecIntLarge;


#if( false )

int main( void ) /* ***************************************************** */
{
    FILE* fp;
    double ti, tp;
    int i, valToFind;
    Rec r;
    Cvec cv;
    initCvec( &cv ); /* Note: MUST initial Cvec v ... for Cvec to work */
   
    puts( HEADER );
   
    ti = clock();
    fp = fopen( "randInt3M.txt", "r" );
    while( 1 == fscanf( fp, "%d", &r.val ) )
    {
        push_backCvec( &cv, &r ); /* since good Rec was obtained */
        /*if( cv.size == 32768*3 ) break; // 32768*11 */
    }
    tp = clock() - ti;
    printf( "%d int's were read from file in %.2f sec's ... ",
            cv.size, tp/CLOCKS_PER_SEC  );

    ti = clock();
    msort( &cv );
    tp = clock() - ti;
    printf( "merge sorted in %.2f sec's", tp/CLOCKS_PER_SEC  );
    printf( "\nand isSorted( &v ) = %d\n", isSorted( &cv ) );


    ti = clock();
    uniqueCvec( &cv );
    tp = clock() - ti;
    printf( "\nuniqueCvec in %.2f sec's", tp/CLOCKS_PER_SEC  );
    printf( " ... and isSorted( &cv ) = %d ", isSorted( &cv ) );
    printf( "\n... and isUniqueCvec( &cv ) = %d\n",
            isUniqueCvec( &cv ) & cv.isSorted );
    printf( "\nAfter uniqueCvec: cv.size = %d, cv.cap = %d\n\n", cv.size, cv.cap );
   

    valToFind = cv.ary[cv.size-1].val;
    ti = clock();
    i = findCvec( &cv, valToFind );
    if( i != -1 )
    {
        eraseCvec( &cv, i );
        tp = clock() - ti;
        printf( "%d was erased ...", valToFind);
        printf( "%d is new end val...\n", cv.ary[cv.size-1].val);
        printf( "find/ereaseCvec in %.2f sec's\n\n", tp/CLOCKS_PER_SEC  );
    }
    else printf( "%d was NOT-found/NOT-erased ...\n\n", valToFind );

    myShowAll( &cv );

    printf( "Before clearCvec: cv.size = %d, cv.cap = %d\n", cv.size, cv.cap );
    clearCvec( &cv );
    printf( "After  clearCvec: cv.size = %d, cv.cap = %d\n", cv.size, cv.cap );
   
    fclose( fp );


    fputs( "\nPress 'Enter' to continue ... ", stdout );
    getchar();
    return 0;
} /* ******************************************************************** */

#endif


You will find the 2 files you need to have available to include ...

"vector_func's.hhf"

"vector.hhf"

at this next link:

http://developers-heaven.net/forum/index.php?topic=2600.0


Here is a speeded up version that reads a line at a time ... (also handles spaces at end of lines)

Code: [Select]
/* msortVecInt2.hla */ /* this version 2012-08-22 */

/*
   http://developers-heaven.net/forum/index.php/topic,46.0.html
*/

program msortVecIntLarge;

const
    InitCap:    uns32   := 3_000_000; // to hold 3 Million random int's
    HEADER:     string  := "HLA program to sort 3 Million random int's from file"
                            #13 #10 "stored in an HLA user defined type Vec...";

type
    Rec:    record
                rval:   int32;
            endrecord;
           
    pRec:   pointer to Rec;
   
procedure freeRec( pr: pRec in eax ); @noframe;
begin freeRec;
    // NO dynamic memory here to free ...
    ret();
end freeRec;

// ok ... after above two types defined ... now can ...

#includeOnce( "vector_func's.hhf" )

procedure myCmpInt( a: pRec in esi; b: pRec in edi ); @returns( "eax" );
begin myCmpInt;
    mov( (type Rec [esi]).rval, eax );
    if( eax <= (type Rec [edi]).rval ) then mov( 1, eax );
    else mov( 0, eax );
    endif;
end myCmpInt;

procedure isSorted( var v: Vec ); @returns( "eax" );
begin isSorted;
    mov( v, ebx );
    mov( (type Vec [ebx]).size, ecx );
    dec( ecx );
    intmul( @size( Rec ), ecx, eax );
    add( (type Vec [ebx]).ary, eax );
    mov( (type Rec [eax]).rval, edi );
    while( (type int32 ecx) > 0 ) do
        dec( ecx );
        sub( @size( Rec ), eax );
        mov( (type Rec [eax]).rval, esi );
        if( (type int32 esi) > edi ) then
            mov( 0, eax );
            break;
        endif;
        mov( esi, edi );
    endwhile;
    mov( 1, eax );
end isSorted;




static
    myVec:  Vec;
    myRec:  Rec;
    fin:    dword;
    tmpStr: string;
   
clock:  timer_t;
   
    line:   str.strvar( 256 ); // lines here are less than 100 char's



begin msortVecIntLarge;

    stdout.put( HEADER, nl nl );
   
    initVec( myVec );

    clock.create();
    clock.start();
   
    fileio.open( "randInt3M.txt", fileio.r );
    mov( eax, fin );
    while( !fileio.eof( fin ) ) do
       
        fileio.gets( fin, line ); // max size fixed above to 256 char's
       
        mov( line, esi );
        mov( (type str.strRec [esi]).length, edx );
       
        if( edx ) then // i.e. if line NOT empty ... trim any spaces from end
            dec( edx );
            while( (type char [esi+edx]) == ' ' ) do dec( edx ); endwhile;
            inc( edx );
            mov( 0, (type char [esi+edx]) ); // ensure 0 terminated
           //mov( edx, (type str.strRec [esi]).length ); // update with new length
           
            while( (type char [esi]) != 0 ) do
                conv.atoi32( [esi] );
                mov( eax, myRec.rval );
                // push( ebx ); push( ecx ); push( esi ); push( edi ); // if needed //
                push( esi );
                push_backVec( myVec, myRec );
                pop( esi );
            endwhile;
           
        endif;

    endwhile;
   
    clock.stop();
    stdout.put( nl "To fill Vec from file ... ms = ", (type uns64 clock.Accumulated), nl );
   
 
    stdout.put( "myVec.size = ", myVec.size,
                ", myVec.capacity = ", myVec.capacity, nl );
 
   
    clock.start();
    mov( &myCmpInt, pMyCmp );
    msortVec( myVec );
    clock.stop();
    stdout.put( nl "To msort ... ms = ", (type uns64 clock.Accumulated), nl );
   
    isSorted( myVec );
    stdout.put( "isSorted( myVec ) = ", (type boolean al), nl );
   
    stdout.put( "myVec.size = ", myVec.size,
                ", myVec.capacity = ", myVec.capacity, nl );
   
    clearVec( myVec );
   
    stdout.puts( nl "Press 'Enter' to exit/continue ... " );
    stdin.readLn();

end msortVecIntLarge;


Now ... a super fast load from file, reading the whole file into one large dynamic buffer in ONE big gulp ... (also handles NON numeric/whitespace at end of file, if any to handle) ...

Code: [Select]
/* msortVecInt3.hla */ /* this version 2012-08-22 */

/*
   http://developers-heaven.net/forum/index.php/topic,46.0.html
*/

program msortVecIntLarge;

const
    InitCap:    uns32   := 3_000_000; // to hold 3 Million random int's
    FNAME:      string  := "randInt3M.txt";
    HEADER:     string  := "HLA program to sort 3 Million random int's from file"
                            #13 #10 "stored in an HLA user defined type Vec...";

type
    Rec:    record
                rval:   int32;
            endrecord;
           
    pRec:   pointer to Rec;
   
procedure freeRec( pr: pRec in eax ); @noframe;
begin freeRec;
    // NO dynamic memory here to free ...
    ret();
end freeRec;

// ok ... after above two types defined ... now can ...

#includeOnce( "vector_func's.hhf" )

procedure myCmpInt( a: pRec in esi; b: pRec in edi ); @returns( "eax" );
begin myCmpInt;
    mov( (type Rec [esi]).rval, eax );
    if( eax <= (type Rec [edi]).rval ) then mov( 1, eax );
    else mov( 0, eax );
    endif;
end myCmpInt;

procedure isSorted( var v: Vec ); @returns( "eax" );
begin isSorted;
    mov( v, ebx );
    mov( (type Vec [ebx]).size, ecx );
    dec( ecx );
    intmul( @size( Rec ), ecx, eax );
    add( (type Vec [ebx]).ary, eax );
    mov( (type Rec [eax]).rval, edi );
    while( (type int32 ecx) > 0 ) do
        dec( ecx );
        sub( @size( Rec ), eax );
        mov( (type Rec [eax]).rval, esi );
        if( (type int32 esi) > edi ) then
            mov( 0, eax );
            break;
        endif;
        mov( esi, edi );
    endwhile;
    mov( 1, eax );
end isSorted;




static
    myVec:  Vec;
    myRec:  Rec;
    fin:    dword;
    tmpStr: string;
   
clock:  timer_t;
   
    buf:    pointer to char;



begin msortVecIntLarge;

    stdout.put( HEADER, nl nl );
   
    initVec( myVec );

    clock.create();
    clock.start();
   
    fileio.open( FNAME, fileio.r );
    mov( eax, fin );
   
    filesys.size( fin );
    mov( eax, ecx );
    inc( eax );     // leave room for terminal 0
    mem.alloc( eax );
    mov( eax, buf );
   
    fileio.read( fin, [eax], ecx );
    if( eax != -1 ) then
   
        if( ecx ) then
       
            dec( ecx );
            mov( buf, esi );
            while( (type int32 ecx) >= 0 && (type char [esi+ecx]) < '0' ||
                   (type char [esi+ecx]) > '9' ) do  dec( ecx );
            endwhile;
            inc( ecx );
            mov( 0, (type char [esi+ecx]) ); // ensure 0 terminated
           
            while( (type char [esi]) != 0 ) do
                conv.atoi32( [esi] );
                mov( eax, myRec.rval );
                // push( ebx ); push( ecx ); push( esi ); push( edi ); // if needed //
                push( esi );
                push_backVec( myVec, myRec );
                pop( esi );
            endwhile;
           
        endif;
       
    else
        stdout.put( "There was a problem reading file ", FNAME, nl );
    endif;
   
    mem.free( buf );
   
    clock.stop();
    stdout.put( nl "To fill Vec from file ... ms = ", (type uns64 clock.Accumulated), nl );
   
 
    stdout.put( "myVec.size = ", myVec.size,
                ", myVec.capacity = ", myVec.capacity, nl );
 
   
    clock.start();
    mov( &myCmpInt, pMyCmp );
    msortVec( myVec );
    clock.stop();
    stdout.put( nl "To msort ... ms = ", (type uns64 clock.Accumulated), nl );
   
    isSorted( myVec );
    stdout.put( "isSorted( myVec ) = ", (type boolean al), nl );
   
    stdout.put( "myVec.size = ", myVec.size,
                ", myVec.capacity = ", myVec.capacity, nl );
   
    clearVec( myVec );
   
    stdout.puts( nl "Press 'Enter' to exit/continue ... " );
    stdin.readLn();

end msortVecIntLarge;
« Last Edit: August 27, 2012, 05:58:51 AM by David »

Offline David

  • Hero Member
  • *****
  • Posts: 647
    • View Profile
Re: Six Fast Steps to Programming in High Level Assembly (HLA) ...
« Reply #18 on: August 07, 2012, 12:20:52 PM »
 Now, using the same file of 3,000,000 random integers as above, try this super fast file read ... (and sort) ... and you don't need to be concerned if there is, or is not, a new-line/white-space sequence at file end :)

Note: using "vector2.hhf", "vector2_func's.hhf" here ...

Code: [Select]
program fileSizeReadDemo_atoi32; // 2012-08-16 //

 
const
    InitCap: uns32 := 3_000_000;
 
#includeOnce( "vector2_func's.hhf" )

type
    Rec:    record
                rval:   int32;
            endrecord;
           
    pRec:   pointer to Rec;
           
procedure myFreeRec( pr: pRec in eax ); @noframe;
begin myFreeRec;
    // no dynamic memory to free ...
    ret();
end myFreeRec;

// re. msort...
procedure myCmpInt( a: pRec in esi; b: pRec in edi ); @returns( "eax" );
begin myCmpInt;
    mov( (type Rec [esi]).rval, eax );
    if( eax <= (type Rec [edi]).rval ) then mov( 1, eax );
    else mov( 0, eax );
    endif;
end myCmpInt;


procedure isSorted( var v: Vec ); @returns( "eax" );
begin isSorted;
    mov( v, ebx );
    mov( (type Vec [ebx]).size, ecx );
    if( ecx > 2 ) then
        dec( ecx );
        intmul( @size( Rec ), ecx, eax );
        add( (type Vec [ebx]).ary, eax );
        mov( (type Rec [eax]).rval, edi );
        while( (type int32 ecx) > 0 ) do
            dec( ecx );
            sub( @size( Rec ), eax );
            mov( (type Rec [eax]).rval, esi );
            if( (type int32 esi) > edi ) then
                mov( 0, eax );
                break;
            endif;
            mov( esi, edi );
        endwhile;
    endif;
    mov( 1, eax );
end isSorted;

 
static
    fin:    dword;
    line:   string;
   
    myVec:  Vec;
    myRec:  Rec;
   
clock:  timer_t;
 

begin fileSizeReadDemo_atoi32;

    clock.create();
    clock.start();
   
    fileio.open( "randInt3M.txt", fileio.r );
    mov( eax, fin );
    filesys.size( fin );
    mov( eax, ecx );
    if( ecx != -1 ) then
        stdout.put( nl "Size of file = ", (type uns32 ecx), " bytes", nl );
        str.alloc( ecx );
        mov( eax, line );
       
        fileio.read( fin, [eax], ecx );     // get whole file into string
       
        mov( line, eax );                   // now ensure 'end' is 'trimmed'
        dec( ecx );
        while( (type char [eax+ecx]) < '0' || (type char [eax+ecx]) > '9' ) do
            dec( ecx );
        endwhile;
        inc( ecx );
       
        mov( ecx, (type str.strRec [eax]).length );
        mov( 0, (type char [eax+ecx]) );    // ensure 0 terminated ...
       
        initVec( myVec, @size(Rec) );       // now get 'words' into a Vec of int32
        mov( &myFreeRec, pFreeRec );        // so can clearVec ... ok
       
        mov( line, esi );
     
        while( (type char [esi]) != 0 ) do
            conv.atoi32( [esi] );
            mov( eax, myRec.rval );
            push( esi );
            //push( ebx ); push( ecx ); push( esi ); push( edi );
            push_backVec( myVec, &myRec );
            pop( esi );
        endwhile;
       
        str.free( line );
        clock.stop();
       
        stdout.put( nl "To fill Vec with int32 from file ... ms = ",
                    (type uns64 clock.Accumulated), nl
                    "myVec.size = ", myVec.size,
                    ", myVec.capacity = ", myVec.capacity, nl );


        clock.start();
        mov( &myCmpInt, pMyCmp );
        msortVec( myVec );
        clock.stop();
       
        stdout.put( nl "To msort Vec ... ms = ",
                    (type uns64 clock.Accumulated) );
       
        isSorted( myVec );
        stdout.put( ", isSorted( myVec ) = ", (type boolean al), nl );

        mov( myVec.size, ecx );
        dec( ecx );
        stdout.put( "myVec.size = ", myVec.size,
                    ", myVec.capacity = ", myVec.capacity, nl );
        intmul( @size( Rec ), ecx, ecx );
        add( myVec.ary, ecx );
        stdout.put( "last 'sorted' value  = '",
                    (type Rec [ecx]).rval, "'" nl );
 
        clearVec( myVec );
       
    else
        stdout.put( "Error calculating file size" nl );
    endif;
    fileio.close( fin );
   
   
    stdout.puts( nl "Press 'Enter' to exit/continue ... " );
    stdin.readLn();
   
end fileSizeReadDemo_atoi32;


You will find the 2 files you need to have available to include ...

"vector2_func's.hhf"

"vector2.hhf"

at this next link:

http://developers-heaven.net/forum/index.php?topic=2600.0
« Last Edit: August 22, 2012, 09:37:21 AM by David »

Offline David

  • Hero Member
  • *****
  • Posts: 647
    • View Profile
Re: Six Fast Steps to Programming in High Level Assembly (HLA) ...
« Reply #19 on: August 20, 2012, 02:45:58 AM »
This next example program, demo's using HLA blobs, for super-fast loading of a (very large) file into a 'file-like-memory-buffer' ... all in one BIG GULP ... then processing from that LARGE HLA BLOB/BUFFER ... (here - a dynamic memory buffer with file like behaviour) ...

Note: it uses the same file of 3,000,000 random integers as the two programs above.  It also demo's a way to handle the problem of whitespace/new-line char's ... (or here, any NON integer char's) ... that might exist at the end of the file of integers.  I found on my 64 bit Windows 7 system, that the load times for method2/method1 were consistently at the ratio 1.4

Ok ... here is the HLA BLOB example ...

Code: [Select]
program blobDemo; // 2012-08-21 //

 
const
    InitCap: uns32 := 3_000_000;
    FNAME:  string := "randInt3M.txt";
 
#includeOnce( "vector2_func's.hhf" )

type
    Rec:    record
                rval:   int32;
            endrecord;
           
    pRec:   pointer to Rec;
           
procedure myFreeRec( pr: pRec in eax ); @noframe;
begin myFreeRec;
    // no dynamic memory to free ...
    ret();
end myFreeRec;

// re. msort...
procedure myCmpInt( a: pRec in esi; b: pRec in edi ); @returns( "eax" );
begin myCmpInt;
    mov( (type Rec [esi]).rval, eax );
    if( eax <= (type Rec [edi]).rval ) then mov( 1, eax );
    else mov( 0, eax );
    endif;
end myCmpInt;


procedure isSorted( var v: Vec ); @returns( "eax" );
begin isSorted;
    mov( v, ebx );
    mov( (type Vec [ebx]).size, ecx );
    if( ecx > 2 ) then
        dec( ecx );
        intmul( @size( Rec ), ecx, eax );
        add( (type Vec [ebx]).ary, eax );
        mov( (type Rec [eax]).rval, edi );
        while( (type int32 ecx) > 0 ) do
            dec( ecx );
            sub( @size( Rec ), eax );
            mov( (type Rec [eax]).rval, esi );
            if( (type int32 esi) > edi ) then
                mov( 0, eax );
                break;
            endif;
            mov( esi, edi );
        endwhile;
    endif;
    mov( 1, eax );
end isSorted;

 
static
    fin:    dword;
    tmpReg: dword;
    line:   string;
   
    myVec:  Vec;
    myRec:  Rec;
   
clock:  timer_t;
   
    blb:    blob.blob;
    c:      char[4];
   
    loops:  uns32 := 5; // so can check load/sort run times  ... x5
   
    sum1:   uns32[2] := [ 0, 0 ];
    sum2:   uns32[2] := [ 0, 0 ];
   
    ratio:  real32;
   



begin blobDemo;

    clock.create();
 
beginLoops:   
   
    clock.start();
   
    fileio.open( FNAME, fileio.r );
    mov( eax, fin );
    filesys.size( fin );
    mov( eax, ecx );
    if( ecx != -1 ) then
        stdout.put( nl "Size of file = ", (type uns32 ecx), " bytes", nl );
        str.alloc( ecx );
        mov( eax, line );
       
        fileio.read( fin, [eax], ecx );     // get whole file into string
       
        mov( line, eax );                   // now ensure 'end' is 'trimmed'
        dec( ecx );
        while( (type char [eax+ecx]) < '0' || (type char [eax+ecx]) > '9' ) do
            dec( ecx );
        endwhile;
        inc( ecx );
       
        mov( ecx, (type str.strRec [eax]).length );
        mov( 0, (type char [eax+ecx]) );    // ensure 0 terminated ...
       
        initVec( myVec, @size(Rec) );       // now get 'words' into a Vec of int32
        mov( &myFreeRec, pFreeRec );        // so can clearVec ... ok
       
        mov( line, esi );
     
        while( (type char [esi]) != 0 ) do
            conv.atoi32( [esi] );
            mov( eax, myRec.rval );
            mov( esi, tmpReg ); // preserve esi ...
            //push( ebx ); push( ecx ); push( esi ); push( edi );
            push_backVec( myVec, &myRec );
            mov( tmpReg, esi ); // retore esi ...
        endwhile;
       
        str.free( line );
        clock.stop();
        add( eax, sum1 );
       
        stdout.put( nl "To fill Vec with int32 from file/string_buf ... ms = ",
                    (type uns64 clock.Accumulated), nl
                    "myVec.size = ", myVec.size,
                    ", myVec.capacity = ", myVec.capacity, nl );


        clock.start();
        mov( &myCmpInt, pMyCmp );
        msortVec( myVec );
        clock.stop();
        add( eax, sum1[4] );
       
        stdout.put( nl "To msort Vec ... ms = ",
                    (type uns64 clock.Accumulated) );
       
        isSorted( myVec );
        stdout.put( ", isSorted( myVec ) = ", (type boolean al), nl );

        mov( myVec.size, ecx );
        dec( ecx );
        stdout.put( "myVec.size = ", myVec.size,
                    ", myVec.capacity = ", myVec.capacity, nl );
        intmul( @size( Rec ), ecx, ecx );
        add( myVec.ary, ecx );
        stdout.put( "last 'sorted' value  = '",
                    (type Rec [ecx]).rval, "'" nl );
                   
        clearVec( myVec );
       
    else
        stdout.put( "Error calculating file size" nl );
    endif;
    fileio.close( fin );
   
   
   
   
    stdout.puts( nl nl "Ok ... now demo of almost as super fast "
                "fileio ... using an HLA blob ..." nl nl );
   
   
    initVec( myVec, @size( Rec ) ); // DON'T FORGET to init... @size( Rec )
   
    clock.start();
   
    blob.a_load( FNAME );
    mov( eax, blb );

    // now trim off any/all NON 0..9 char's from end of blob ...
    // and reset length ...
   
    //blob.maxlen( blb );
    //stdout.put( "blob.maxlen = ", (type uns32 eax), nl );
 
    blob.length( blb );
    //stdout.put( "blob.length = ", (type uns32 eax), nl );
   
    mov( eax, ecx ); // mov (present) blob length into ecx ...
    dec( ecx );     // so can 'test' content of last char's in blob
    while( (type int32 ecx) >= 0 ) do
   
        //get at last char per either of the 2 lines below ...
        //blob.readAt( blobPointer, buffer, index, count );
        //blob.readAt( blobPointer, [eax], 2999999, 1 );
       
        blob.readAt( blb, &c, ecx, 1 );
        mov( c, al );
        if( al < '0' || al > '9' ) then
            dec( ecx );
        else
            break;
        endif;
    endwhile;
    inc( ecx ); // get 'new' length
   
    blob.setLength( blb, ecx ); // Ok ... update with 'new' blob length
   
    // Now can get each int32 from blob without worrying about 'crash' ...
    // if there were any non 0..9 char's, after n'th 0..9 char, before eof
   
    while( !blob.eof( blb ) ) do
        blob.geti32( blb );
        mov( eax, myRec.rval );
        push_backVec( myVec, &myRec );
    endwhile;
   
    blob.free( blb ); // free (not destroy) since used alloc via blob.a_load
   
    clock.stop();
    add( eax, sum2 );
   
   
    stdout.put( nl "To fill Vec with int32 from file/blob ... ms = ",
                    (type uns64 clock.Accumulated), nl
                    "myVec.size = ", myVec.size,
                    ", myVec.capacity = ", myVec.capacity, nl );


    clock.start();
    mov( &myCmpInt, pMyCmp ); // done above alraedy
    msortVec( myVec );
    clock.stop();
    add( eax, sum2[4] );
   
    stdout.put( nl "To msort Vec ... ms = ",
                (type uns64 clock.Accumulated) );
   
    isSorted( myVec );
    stdout.put( ", isSorted( myVec ) = ", (type boolean al), nl );

    mov( myVec.size, ecx );
    dec( ecx );
    stdout.put( "myVec.size = ", myVec.size,
                ", myVec.capacity = ", myVec.capacity, nl );
    intmul( @size( Rec ), ecx, ecx );
    add( myVec.ary, ecx );
    stdout.put( "last 'sorted' value  = '",
                (type Rec [ecx]).rval, "'" nl );
               
    clearVec( myVec );
   
    dec( loops );
    jnz( beginLoops );
   
   
    stdout.put( nl nl
                "Summery of times ..." nl nl
                "Load 1st method sum:", sum1:6, nl
                "Sort            sum:", sum1[4]:6, nl
                "Load 2nd method sum:", sum2:6, nl
                "Sort            sum:", sum2[4]:6, nl nl );
               
    finit();
    fild( sum2[0] );
    fild( sum1[0] );
    fdivp();
    fstp( ratio );    // POP and store sto int ...
    stdout.put( "Ratio of load times method2/method1 =", ratio:5:2, nl );


   
    stdout.puts( nl "Press 'Enter' to exit/continue ... " );
    stdin.readLn();
   
end blobDemo;


You will find the 2 files you need to have available to include ...

"vector2_func's.hhf"

"vector2.hhf"

at this next link:

http://developers-heaven.net/forum/index.php?topic=2600.0


« Last Edit: August 27, 2012, 03:50:30 AM by David »