BBC BASIC for Windows
« Compiling ASM program containing array labels »

Welcome Guest. Please Login or Register.
Apr 5th, 2018, 9:59pm



ATTENTION MEMBERS: Conforums will be closing it doors and discontinuing its service on April 15, 2018.
Ad-Free has been deactivated. Outstanding Ad-Free credits will be reimbursed to respective payment methods.

If you require a dump of the post on your message board, please come to the support board and request it.


Thank you Conforums members.

BBC BASIC for Windows Resources
Online BBC BASIC for Windows documentation
BBC BASIC for Windows Beginners' Tutorial
BBC BASIC Home Page
BBC BASIC on Rosetta Code
BBC BASIC discussion group
BBC BASIC for Windows Programmers' Reference

« Previous Topic | Next Topic »
Pages: 1  Notify Send Topic Print
 thread  Author  Topic: Compiling ASM program containing array labels  (Read 2276 times)
David Williams
Developer

member is offline

Avatar

meh


PM

Gender: Male
Posts: 452
xx Compiling ASM program containing array labels
« Thread started on: Jun 1st, 2009, 03:26am »

Should this program be generating this error when compiled: "Crunch failed: assembler syntax error" ?

Code:
      DIM code% 256
      PROCassemble
      PRINT USR( code% )
      END
      
      DEF PROCassemble
      LOCAL pass%
      DIM label%(10)
      FOR pass%=0 TO 2 STEP 2
        P% = code%
        [OPT pass%
        
        .label%(0)
        mov eax, 123456
        ret
        
        ]
      NEXT pass%
      ENDPROC
 


It runs fine from the IDE, but it won't compile unless all the crunch options are unset. I doubt it's a bug,
although in a way I really hope that it is!


David.
User IP Logged

admin
Administrator
ImageImageImageImageImage


member is offline

Avatar




PM


Posts: 1145
xx Re: Compiling ASM program containing array labels
« Reply #1 on: Jun 1st, 2009, 08:13am »

Quote:
Should this program be generating this error when compiled: "Crunch failed: assembler syntax error" ?

The cruncher is more fussy about assembler syntax than the run-time interpreter, and when I suggested that you could use array elements as assembler labels I'd forgotten that it's not strictly allowed. I've checked on the 'original' (BBC Micro) BBC BASIC and it definitely does not allow array elements as labels.

So the cruncher is actually quite correct in rejecting this. The 'bug', if you like, is that the interpreter allows it (and that I recommended it!).

I'll have to give some thought to the best way of resolving this in the long term, because the Wiki also recommends the use of array elements as labels (in the article about simulating assembler macros).

Thanks for pointing this out.

Richard.
User IP Logged

admin
Administrator
ImageImageImageImageImage


member is offline

Avatar




PM


Posts: 1145
xx Re: Compiling ASM program containing array labels
« Reply #2 on: Jun 1st, 2009, 4:20pm »

Having thought about it, I'm sure it wouldn't be right for the compiler to allow array elements as assembler labels. Accordingly, I have modified the Wiki article which used this technique so that it no longer does so. I must try to reprogram my brain so that I don't recommend it again either!

I don't propose to modify the interpreter so that it also disallows array elements (it would be difficult); this feature will join the set of things which you can 'get away with' in the interpreter but not when compiled.

If you're still affected by the limitation of 1200 or so labels before a register name is generated (and I do intend to fix this in a future release) you can use structure members as labels (in both the interpreter and the compiler). In fact that's probably a nicer solution than array elements anyway:

Code:
      DIM code% 256
      PROCassemble
      PRINT USR( code% )
      END
      
      DEF PROCassemble
      LOCAL pass%
      DIM label{a,b,c,d}
      FOR pass%=0 TO 2 STEP 2
        P% = code%
        [OPT pass%
        jmp label.a
        .label.a
        mov eax, 123456
        ret
        ]
      NEXT pass%
      ENDPROC 

Richard.
User IP Logged

David Williams
Developer

member is offline

Avatar

meh


PM

Gender: Male
Posts: 452
xx Re: Compiling ASM program containing array labels
« Reply #3 on: Jun 1st, 2009, 6:49pm »

on Jun 1st, 2009, 4:20pm, Richard Russell wrote:
If you're still affected by the limitation of 1200 or so labels before a register name is generated (and I do intend to fix this in a future release) you can use structure members as labels (in both the interpreter and the compiler). In fact that's probably a nicer solution than array elements anyway:

Thanks for looking into this, I'm very grateful. I had spent two hours or possibly more replacing well over a hundred assembler labels in GFXLIB with array labels (with many more to do). And it worked beautifully... until I thought I might try compiling a simple test program! Then the blood drained from my face as the realisation dawned on me...

The 'structure members as labels' solution sounds nice for a small set of routines, but GFXLIB has over a hundred routines (I think) and I don't really fancy A) re-modifying the 50-or-so routines I've already modified to use array labels, and B) declaring a structure for each routine.

What with the aforementioned array labels problem and the issues arising from my attempt to fully modulize GFXLIB (namely, embedding of the library's modules and other resource files), I think it'd be prudent to cut my losses and leave GFXLIB as it is in its long, sprawling, linear form. If anyone wants to load it into the IDE, they'll just have to adjust the IDE's 'Initial user memory' setting.

Thanks again.


David.
« Last Edit: Jun 1st, 2009, 6:52pm by David Williams » User IP Logged

admin
Administrator
ImageImageImageImageImage


member is offline

Avatar




PM


Posts: 1145
xx Re: Compiling ASM program containing array labels
« Reply #4 on: Jun 1st, 2009, 10:07pm »

Quote:
The 'structure members as labels' solution sounds nice for a small set of routines, but GFXLIB has over a hundred routines (I think)

I don't know exactly how you tried to use the array-element method but I presume you didn't use one large array for all the labels but instead a separate array for each routine or small group of routines. In that case I would have thought a straightforward search-and-replace of (0) to .a, (1) to .b etc. would have done most of the conversion.

Of course you'd also have to replace each array declaration with an equivalent structure declaration, but assuming the size of each array is quite small (say fewer than 20 elements) that should be pretty easy too. You would necessarily need to use the same member names for each structure (otherwise the method offers no advantage over separate labels) so again a search-and-replace will do most of the work.

So maybe converting to the structure-member method wouldn't be too much effort after all.

Richard.
User IP Logged

David Williams
Developer

member is offline

Avatar

meh


PM

Gender: Male
Posts: 452
xx Re: Compiling ASM program containing array labels
« Reply #5 on: Jun 1st, 2009, 10:37pm »

on Jun 1st, 2009, 10:07pm, Richard Russell wrote:
I don't know exactly how you tried to use the array-element method but I presume you didn't use one large array for all the labels but instead a separate array for each routine or small group of routines. In that case I would have thought a straightforward search-and-replace of (0) to .a, (1) to .b etc. would have done most of the conversion.


I used a two-dimensional array: label%( numRoutines%-1, 9 ), allowing each of the main routines to have upto 10 'sub-labels'.

Just to illustrate, here's one routine from GFXLIB (routine #24):

Code:
        ;REM.
        ;REM.  ****************|******************************************************************************
        ;REM.  *               |                                                                             *
        ;REM.  *       Routine | (24) Plot                                                                   *
        ;REM.  *               |                                                                             *
        ;REM.  *       Purpose | Plots a raw 32bpp bitmap (or 'sprite')                                      *
        ;REM.  *               |                                                                             *
        ;REM.  *  Entry params | dispVars, bmAddr, bmW, bmH, bmX, bmY                                        *
        ;REM.  *               |                                                                             *
        ;REM.  *       Example | SYS GFXLIB_Plot, dispVars{}, ballspr%, 32, 32, ballx%, bally%               *
        ;REM.  *               |                                                                             *
        ;REM.  *         Notes | Black pixels (i.e. those of value &xx000000) are ignored (i.e. not plotted) *
        ;REM.  *               |                                                                             *
        ;REM.  ****************|******************************************************************************
        ;REM.
        
        .GFXLIB_Plot
        
        ;
        ; SYS GFXLIB_Plot, dispVars, bmAddr, bmW, bmH, bmX, bmY
        ;
        
        pushad
        
        ;REM. ESP+36 = dispVars
        ;REM. ESP+40 = bmAddr
        ;REM. ESP+44 = bmW
        ;REM. ESP+48 = bmH
        ;REM. ESP+52 = bmX
        ;REM. ESP+56 = bmY
        
        ;REM. --------------------------------------------------------------
        ;REM. Setup the entry calling params for the bitmap clipping routine
        ;REM. --------------------------------------------------------------
        
        mov eax, [esp+36]                       ; EAX = ptr to params blk
        
        cmp dword [eax+28], TRUE
        jne near label%(24,0)                   ; .GFXLIB_Plot__exit
        
        ;REM. copy GFXLIB_Plot's entry vars from the stack to varsblk (makes life somewhat easier)
        
        mov ebx,[esp+40] : mov [varsblk+64],ebx ; varsblk+64 = bmAddr
        mov ebx,[esp+44] : mov [varsblk+68],ebx ; varsblk+68 = bmW
        mov ebx,[esp+48] : mov [varsblk+72],ebx ; varsblk+72 = bmH
        mov ebx,[esp+52] : mov [varsblk+76],ebx ; varsblk+76 = bmX
        mov ebx,[esp+56] : mov [varsblk+80],ebx ; varsblk+80 = bmY
        
        ;REM. Call the clipping routine (GFXLIB_clip) after PUSHing the required vars onto the stack
        
        ;REM. SYS GFXLIB_clip, dispVars, bmW, bmH, bmX, bmY, clipValsBlk
        
        push (varsblk+128)                      ; ptr to clipValsBlk
        push dword [varsblk+80]                 ; bmY
        push dword [varsblk+76]                 ; bmX
        push dword [varsblk+72]                 ; bmH
        push dword [varsblk+68]                 ; bmW
        push eax                                ; ptr to params blk
        call GFXLIB_clip
        
        ;REM.
        ;REM. clipValsBlk
        ;REM.
        ;REM.      +128    plotFlag (TRUE or FALSE) - if FALSE, do not attempt to plot/display bitmap
        ;REM.      +132    clipFlag (TRUE or FALSE) - if TRUE then clipping is required
        ;REM.      +136    startX
        ;REM.      +140    startY
        ;REM.      +144    numRows
        ;REM.      +148    rowLen
        ;REM.      +152    skipRows
        ;REM.      +156    skipPxls
        ;REM.
        
        cmp [varsblk+128], dword TRUE           ; check plotFlag
        jne label%(24,0)                        ; GFXLIB_Plot__exit ; exit if plotFlag=FALSE
        
        ;REM.
        ;REM. bmBuffO% = bmBuffAddr% + 4*(params.bmBuffW%*clipvals.startY% + clipvals.startX%)
        ;REM. bmW4% = 4*bmW%
        ;REM. bmBuffW4% = 4*bmBuffW%
        ;REM. bmAddr% += 4*(clipvals.skipRows% + clipvals.skipPxls%)
        ;REM.
        ;REM. FOR Y%=clipvals.numRows%-1 TO 0 STEP -1
        ;REM.   FOR X%=clipvals.rowLen%-1 TO 0 STEP -1
        ;REM.     bmBuffO%!(4*X%) = bmAddr%!(4*X%)
        ;REM.   NEXT X%
        ;REM.   bmAddr% += bmW4%
        ;REM.   bmBuffO% += bmBuffW4%
        ;REM. NEXT Y%
        ;REM.
        
        ;----*----*----*----*----*----*----*----|
        
        ; compute initial/starting offset into the 'bmp buffer' (bmBuffO)
        
        ; EAX = ptr to params blk
        
        
        mov ebx, [eax + 0]                      ; load base addr of 'bmp buffer' (bmpBuffAddr)
        mov ecx, [varsblk + 140]                ; startY
        imul ecx, [eax + 4]                     ; = startY*bmpBuffW
        add ecx, [varsblk + 136]                ; = startY*bmpBuffW + startX
        shl ecx, 2                              ; = 4*(startY*bmpBuffW + startX)
        add ecx, ebx                            ; = bmpBuffAddr + 4*(startY*bmpBuffW + startX)
        
        mov edi, [varsblk + 64]                 ; bmAddr
        
        mov ebx, [varsblk + 152]                ; skipRows
        add ebx, [varsblk + 156]                ; skipRows+skipPxls
        shl ebx, 2                              ; 4*(skipRows + skipPxls)
        add edi, ebx                            ; bmAddr += 4*(skipRows + skipPxls)
        
        mov ebp, [varsblk + 68]                 ; bmW
        shl ebp, 2                              ; = 4*bmW
        
        mov eax, [eax + 4]                      ; bmBuffW
        shl eax, 2                              ; = 4*bmBuffW
        
        mov esi, [varsblk + 144]                ; numRows (Y-loop counter)
        dec esi                                 ; numRows -= 1
        
        .label%(24,1)                           ; .GFXLIB_Plot__yloop        
        push esi                                ; preserve ESI (Y-loop counter)
        
        mov esi, [varsblk + 148]                ; rowLen (X-loop counter)
        dec esi                                 ; rowLen -= 1
        
        .label%(24,2)                           ; .GFXLIB_Plot__xloop
        mov edx, [edi + 4*esi]                  ; load dword from source bitmap
        test edx, &00FFFFFF                     ; is it 0 ?
        jz label%(24,3)                         ; GFXLIB_Plot__next_pxl ; skip (i.e. don't plot) if so
        
        mov [ecx + 4*esi], edx                  ; write dword to destination bitmap buffer
        
        .label%(24,3)                           ; .GFXLIB_Plot__next_pxl
        dec esi                                 ; X -= 1
        jge label%(24,2)                        ; GFXLIB_Plot__xloop ; loop if X >= 0
        
        add edi, ebp                            ; bmAddr += 4*bmW
        add ecx, eax                            ; bmBuffAddr += 4*bmBuffW
        
        pop esi                                 ; recover numRows (Y-loop)
        dec esi                                 ; Y -= 1
        jge label%(24,1)                        ; GFXLIB_Plot__yloop ; loop if Y >= 0
        
        .label%(24,0)                           ; .GFXLIB_Plot__exit
        popad
        ret (6*4) 



I would have been perfectly happy with the 2D-array approach if only the Compiler was happy with it.


David.
User IP Logged

admin
Administrator
ImageImageImageImageImage


member is offline

Avatar




PM


Posts: 1145
xx Re: Compiling ASM program containing array labels
« Reply #6 on: Jun 2nd, 2009, 08:34am »

Quote:
I used a two-dimensional array

OK. Personally I'm not keen on that approach, partly because it runs somewhat contrary to the principle of 'information hiding' (having a data structure shared between more than one routine that needn't be) and partly because it makes the labels so 'anonymous' (all called 'label' something!).

I think my preferred approach (had it worked!) would have been to use a separate array for each routine, perhaps with the same name as the routine itself. So the routine GFXLIB_Plot would have had labels GFXLIB_Plot(0), GFXLIB_Plot(1) etc.

If I was faced with converting what you've got to a structure-member approach (which again I'd want to be self-contained to each routine) I'd write a little utility in BASIC to do it!

Richard.
User IP Logged

David Williams
Developer

member is offline

Avatar

meh


PM

Gender: Male
Posts: 452
xx Re: Compiling ASM program containing array labels
« Reply #7 on: Jun 2nd, 2009, 10:04am »

on Jun 2nd, 2009, 08:34am, Richard Russell wrote:
OK. Personally I'm not keen on that approach, partly because it runs somewhat contrary to the principle of 'information hiding' (having a data structure shared between more than one routine that needn't be) and partly because it makes the labels so 'anonymous' (all called 'label' something!).

You've probably noticed that I tend to comment my code verbosely! So, for me personally,
the 'anonymous' label names aren't a problem because I always include an informative comment
on the same line:

Code:
.label%(37,3)              ; .GFXLIB_AlphaBlend__skip

jmp label%(37,5)           ; GFXLIB_AlphaBlend__exit

etc. 



on Jun 2nd, 2009, 08:34am, Richard Russell wrote:
If I was faced with converting what you've got to a structure-member approach (which again I'd want to be self-contained to each routine) I'd write a little utility in BASIC to do it!

Well, again, thanks for another excellent suggestion, but I best channel my energy into
improving the efficiency of existing routines, developing new ones, writing more examples,
and finishing the currently very poor documentation.


David.
User IP Logged

Pages: 1  Notify Send Topic Print
« Previous Topic | Next Topic »

| |

This forum powered for FREE by Conforums ©
Terms of Service | Privacy Policy | Conforums Support | Parental Controls