The Reusing Choice  ...



Each Assembler comes with its implied 'programming philosophy' and the one of RosAsm is in some way being  a 'Specific Assembler':


It is Specific in a way that it outputs only one type of file (I think its better having a tool doing properly only one thing than doing many things but, even if properly, always, at least, with much configuration and usage complications).


It is Specific, too, in that the way that it implies something I call a Specific-Programming-Style. What I mean exactly is a bit difficult to explain but it entirely stands in the expression... It is simpler to explain it as: 'opposed to Modular-Programming-Style'.


Modular programming in Assembler does not make much sense. If one wants to do modular programming, its better to use Basic. It does it perfectly. Now, the fact is that many programmers do not want to always re-invent the wheel, and want to easily reuse something , in some way, I.E. already written chunks of Code.


In the good old DOS time, Static Libraries were very useful to save one from seemingly endless Compilation times. Even today, with some Assemblers - Say, MASM, which is particularly slow - such a Code-Reuse Method may be of some interest. Given the actual performances of hardware, and given the Compilation speed of RosAsm, this Compilation times argument falls flat on its face.


In many other Assemblers, you still have LIBs and INCs, and this is, yet today, the HLL way, but, once Some code is saved as 'reusable'  this way, it becomes Black-Box. The bad thing with Black-Boxes is that you will forget what is inside, and, because reusing is easier than verifying what we are really doing, there are many chances that you will run inaccurate solutions to your programming problems.


An important point, with traditional Libraries, is that such an implementation would completely break down two of the most important features of RosAsm , that make the developments fast and easy: 1) Right-Click advanced Searches and the 2) Source Level [Run]-Time Debugging.


To make a Routine reusable, with these features, you have to make it hold all expected (and unexpected) possibilities. This is to say that you will run  big engines to solve tiny problems, in most circumstances.


Facing these problems, I have had to implement advanced Code-Reuse features in RosAsm, in order to make it a really up-to-date Development Tool.


The main way I have chosen, for reusing Code, is a feature called [Clip]. There is a 'Clips' File aside RosAsm that the user can edit, in which he can save his precious chunks of code and templates. Inside the Main Editor, there is a Menu option that runs a Clips Dialog allowing to choose / customize / Save in ClipBoard. Then, the user pastes it inside his source. Once done, he can adapt the pasted code to his real requirements. All of this is not much longer than LIBs and INCs techniques, but is far better from an Assembly point of view.


Another method, for the programmers who really want 'Libraries', is to consider the use of the TITLE feature (see Source_Editor [TITLE]), as an intermediate solution: We could as well call the TITLE saving, reloading, updating methods a kind of ''Source Level Library'' method. It is quite simple, to save the Library under the .asm from ([Ctrl] [S], and / or to save a ready to reuse Application with only the Base and the Library inside (a kind of extended 'BaseX.exe' File). At least, this intermediate solution will enable you with all the so useful features of Right-Click and with a direct pointing in error cases, if nothing else...


You will notice, too, that with LIBs and INCs techniques, the code Templates are often heavily optimized, in order to try to save with one hand, the time spoiled with the other hand. This way of doing things is then not only stupid, from a technical point of view, but, even worse, if you want to re-read the included chunks of code, you will have much more difficulties than with the simple strategy optimizing allowed by simple code pasting and adapting.


Another great thing with the [Clip] choice, compared to LIBs is that you do not have to memorize anything (what name, what parameters, what registers to preserve, and so on).


Let us consider two versions of a String length function. The first one is proposed in the Library of MASM32 package:


; ##############################


    .386

    .model flat, stdcall

    option casemap :none   ; case sensitive


    .code


; ###############################


StrLen proc item:DWORD


  ; -------------------------------------------------------------

  ; This procedure has been adapted from an algorithm written by

  ; Agner Fog. It has the unusual characteristic of reading up to

  ; three bytes past the end of the buffer as it uses DWORD size

  ; reads. It is measurably faster than a classic byte scanner on

  ; large linear reads and has its place where linear read speeds

  ; are important.

  ; -------------------------------------------------------------


    push    ebx

    mov     eax,item               ; get pointer to string

    lea     edx,[eax+3]            ; pointer+3 used in the end

  @@:     

    mov     ebx,[eax]              ; read first 4 bytes

    add     eax,4                  ; increment pointer

    lea     ecx,[ebx-01010101h]    ; subtract 1 from each byte

    not     ebx                    ; invert all bytes

    and     ecx,ebx                ; and these two

    and     ecx,80808080h    

    jz      @B                     ; no zero bytes, continue loop

    test    ecx,00008080h          ; test first two bytes

    jnz     @F

    shr     ecx,16                 ; not in the first 2 bytes

    add     eax,2

  @@:

    shl     cl,1                   ; use carry flag to avoid branch

    sbb     eax,edx                ; compute length

    pop     ebx


    ret


StrLen endp


; ###############################


end



The Second one is the one I wrote in the default RosAsm Clips File:


mov edi StringPointer, ecx 0-1, al 0

repne scasb

mov eax 0-2 | sub eax ecx      ; Length in eax.



As you can see, the code of the include version is highly optimized. It applies the search upon dWords instead of bytes, and, so forth tends to run four times faster than my version, when parsing very long strings... if they are both structured and called in the same way.


Now, if you test these two routines on very short string, this will not be true. If you test upon middle length strings, the organization (simple code Lines vs independent Procedure) will make the speed difference visible or not. For very long chunks of text, in real life programming, we simply avoid, as long as possible to continuously call for such routines. The best strategy, anyway, is to manage two Variables: One for the length and one for the End_Of_Text all along text modifications.


So, the results of implementing such reusable black-boxes are:


Visual Basic tendencies in programming..

Less readable code.

Decrease of flexibility (what if you have to search for Carriage Return instead of zero?).

Making easy to use inaccurate Strategy solutions.

Loss of control. Example, both examples destroy ecx, but in my version, once pasted in your source, you just have it visible.

~~~~~~~