Author |
Topic: Compiling ASM program containing array labels (Read 2276 times) |
|
David Williams
Developer
member is offline

meh

Gender: 
Posts: 452
|
 |
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.
|
|
Logged
|
|
|
|
admin
Administrator
member is offline


Posts: 1145
|
 |
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.
|
|
Logged
|
|
|
|
admin
Administrator
member is offline


Posts: 1145
|
 |
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.
|
|
Logged
|
|
|
|
David Williams
Developer
member is offline

meh

Gender: 
Posts: 452
|
 |
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.
|
|
|
|
admin
Administrator
member is offline


Posts: 1145
|
 |
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.
|
|
Logged
|
|
|
|
David Williams
Developer
member is offline

meh

Gender: 
Posts: 452
|
 |
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.
|
|
Logged
|
|
|
|
admin
Administrator
member is offline


Posts: 1145
|
 |
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.
|
|
Logged
|
|
|
|
David Williams
Developer
member is offline

meh

Gender: 
Posts: 452
|
 |
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.
|
|
Logged
|
|
|
|
|