5.  ASM Portion

Back Home Up

In the beginning, I gave an example of an assembly langauge program.  But it wasn't complete.  The ML assembler really wants a little bit more to get the job done right.

The assembly module

Here's the complete assembly program used to make the DATA statements in the QBASIC program mentioned before.

 .MODEL MEDIUM, BASIC
 .386
 .CODE
 ReverseStr     PROC    strlen:PTR WORD, strofs:PTR WORD
                mov     bx, strlen      ; put offset of length into BX.
                mov     cx, [bx]        ; put length into CX.
                mov     bx, strofs      ; put offset of string's offset into BX.
                mov     bx, [bx]        ; point BX to the start of the string.
                mov     di, bx          ; compute DI so that it points to the
                add     di, cx          ;   end of the string + 1.
                .WHILE (cx > 1)
                  dec     di            ; backup DI by one character.
                  mov     al, [di]      ; get the tail char into AL.
                  xchg    al, [bx]      ; exchange it with the head char.
                  mov     [di], al      ; move the head char to the tail.
                  inc     bx            ; advance BX by one character.
                  sub     cx, 2         ; finished another 2, more?
                .ENDW
                ret
 ReverseStr     ENDP
                END  

If you aren't already, you will need to become familiar with writing assembly code like this.  There is no other way around it.  I haven't written any tutorials on this, but I've included some links to a very good assembly language tutorial, elsewhere.  If you need to, read them.

The above code will assemble, though.  And it works.

Parameters values and CALL ABSOLUTE

If you look at the above routine at the PROC statement, you will see that there are two paramters listed there.  Those correspond to the first two parameters given in the CALL ABSOLUTE in the QBASIC program.  This is how information is passed between the assembly code and the QBASIC program.  Keep in mind that it is vital that these elements match, in order and count, with those listed in the CALL ABSOLUTE statement.  Otherwise, bad things happen such as a crashed computer.

Also, notice that it takes two instructions to get the value desired because CALL ABSOLUTE passes the address of its parameters and not their values.  The first instruction gets the address.  The second instruction uses that address to get the value.

Normally, you also won't often need segment register overrides since QBASIC puts most things in the group called DGROUP and sets up the DS register to point there by default.  If this doesn't make any sense to you, you need to read some of the references I refer you to elsewhere.  Teaching about segmented memory on the x86 and the assembler directives and segment register overrides needed to manage this memory exceeds the scope of anything I can say here.

Returning values via CALL ABSOLUTE

The above routine passes back the modified string.   But it has the added advantage of not needing to change the string's size.

If you'd like to change the size of a string in QBASIC, you'd need access to the string's descriptor.  More than that, you'd need some way to either allocate more string space for the string or else return excess space.  Either way you cut it, it's hard.  QBASIC does have subroutines for performing these tasks, but it doesn't tell you how to call or use them.  So when working with strings, or any arrays for that matter, you shouldn't plan on changing their size.  Just work with what you are given and live with it.

For simple variables like INTEGER or LONG, you can use the offset pointer you are provided to modify their value before returning.  That way, the QBASIC program can use those variables after the CALL ABSOLUTE and observe the changes you made.  The above routine didn't need to do that, so it doesn't show you how.  But it's quite easy and you should become familiar enough with assembly coding to understand how to add such an instruction on your own.  Consider it a problem left as an exercise for you.

For other variables, such as SINGLE or DOUBLE, these use floating point formats that require a more advanced level of assembly language experience.  I do provide a section on floating point formats and a program called FLOAT, which you can use to experiment with these values.  But be aware that if you are new to assembly, you should avoid trying to pass these values.  There are many issues to master before using them.

 

Last updated: Thursday, June 17, 2004 19:28