gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

ASM > my code wont compile intline??

#8651 - slip - Thu Jul 17, 2003 12:31 pm

I've compiled this code using glodroad but when I try and implement it inline it doesn't work.

Code:
void drawLine(u32 x, u32 max, u32 min, u32 c, u32 b)
{
   /*
   ;;register
   ;;r0 - the x value(incoming)->(changed internally to minimum)
   ;;r1 - the y counter(internally)->but(incoming)is maximum
   ;;r2 - the wall minimum(incoming)
   ;;r3 - the colour(incoming)
   ;;r4 - temp (int) -> (inc buffer)
   ;;r5 - temp
   ;;r6 - temp
   */
   asm("   
      .ALIGN
      .ARM
   ldr r5,=#240
   mul r6,r1,r5
   add r6,r6,r4
   add r6,r0,r6

   mul r7,r2,r5
   add r0,r0,r4
   add r0,r0,r7

moreline:
   strb r3,[r1]
   sub r6,r6,#240
   cmp r6,r0
   bne moreline

      " :
      /* No output */ :
      "r" (x), "r" (max), "r" (min), "r" (c), "r" (b):
      "r5", "r6");

}


I get two errors
Error: Bad expression
Error:Grabage following instruction

the line numbers refer to a file in a temp folder, I've looked for the file but its not there. I don't know which lines the errors are refering to.

can anyone help?
thanks
_________________
[url="http://www.ice-d.com"]www.ice-d.com[/url]

#8653 - Quirky - Thu Jul 17, 2003 12:37 pm

Add -save-temps to keep your temp files to find the error. And you have to add a newline "\n" at the end of each line of inlined assembler for it to compile.

#8655 - slip - Thu Jul 17, 2003 12:55 pm

Thanks for the tip....
Ok... the source of the problem is
ldr r5,=#240
=\.. its the only ldr instruction I have there. it looks fine to me though... (I've only been doing asm for two days)...
I changed ldr to mov.... and its compiled... I don't see why though... any suggestions?
_________________
[url="http://www.ice-d.com"]www.ice-d.com[/url]

#8659 - slip - Thu Jul 17, 2003 1:28 pm

this is unreal... I just ran a few tests....
when calling the function it does not work correctly.
but if set the values for the registers in my asm then I get the correct result... its as though the parameters are not being passed or I'm using the incorrectly.

I'm assuming
void drawLine(u32 x, u32 max, u32 min, u32 c, u32 b)

r0 x
r1 max
r2 min
r3 c
r4 b

=\
thanks again
_________________
[url="http://www.ice-d.com"]www.ice-d.com[/url]

#8661 - Lupin - Thu Jul 17, 2003 2:31 pm

Your code looks interesting to me, what does it do? How could you draw an line with just one X coordinate and some other vars (wich I don't understand what they do)?

#8684 - slip - Fri Jul 18, 2003 12:11 am

the routine is only ment to draw a vertical line. Thus you only need one x co-ordinate, the maximum and minimum y values, colour and the buffer to write to.

The code sets a register as the maximum y + x + the buffer, and another with the minimum, each loop the code subtracts one line (240bytes) from the maximum y register and when that register - the minimum one == 0 then the loop stops.

The problem at the moment is the function inputs arn't working properly. When calling from C++ the values don't seem to come through to r0-r4 and I can't work out why.
_________________
[url="http://www.ice-d.com"]www.ice-d.com[/url]

#8701 - Master S - Fri Jul 18, 2003 10:01 am

I think that only the first 3 (or 4) parameters are given directly in registers. The rest is pushed on the stack

#8737 - torne - Fri Jul 18, 2003 8:52 pm

Master S is right. Only four arguments are passed in registers, the fifth and further arguments are pushed onto the stack by the caller. Read the ARM/Thumb Procedure Call Standard, available from arm.com; it explains the ARM calling conventions.

Torne

#8753 - slip - Sat Jul 19, 2003 3:55 am

Thanks for that. I looked at the document and this is what it says...

o Loading the first 4 words into integer registers a1-a4 (lowest addressed into a1). If there are fewer than 4
words, they are loaded into a1-a3, a1-a2, or a1 only.

o Pushing remaining words onto the stack in reverse order (so the first remaining parameter word is at
VAL(SP), the second at VAL(SP)+4, and so on).

now does that means I can just use a ldm and load r4-r7 like this:

ldmfd sp!,{r4-r7}

is it full-decending or something else? or is this wrong all together?
thanks
_________________
[url="http://www.ice-d.com"]www.ice-d.com[/url]

#8754 - sgstair - Sat Jul 19, 2003 3:57 am

Hello slip,
slip wrote:
Thanks for the tip....
Ok... the source of the problem is
ldr r5,=#240
=\.. its the only ldr instruction I have there. it looks fine to me though... (I've only been doing asm for two days)...
I changed ldr to mov.... and its compiled... I don't see why though... any suggestions?


The source of your problem is the #...
when using gnu's as, you can mov r5,#number, or ldr r5,=number, but not ldr r5,=#number

Hope this helps :)
-Stephen

#8759 - slip - Sat Jul 19, 2003 5:59 am

=).. thanks for that sgstair I wondered what was going on.
_________________
[url="http://www.ice-d.com"]www.ice-d.com[/url]

#8761 - slip - Sat Jul 19, 2003 6:20 am

I've changed the code a bit....
Code:

void drawLine(u32 x, u32 max, u32 min, u32 c, u32 b, u32 tx, u32 *t, u32 scale)
{
   /*
   ;;register
   ;;r1 - the x value(incoming)->(changed internally to minimum)
   ;;r2 - the y counter(internally)->but(incoming)is maximum
   ;;r3 - the wall minimum(incoming)
   ;;r4 - the colour(incoming)
   ;;r5 - incoming buffer
   */
//========ASM==============
   //Draw vertical line based on ^^
   asm("   
      .ALIGN
      .ARM
   ldmfd sp!,{r5-r8}

   mov r9,#240
   mul r10,r2,r9
   add r8,r8,r5
   add r8,r1,r10

   mul r11,r3,r7
   add r1,r1,r5
   add r1,r1,r11

moreline:
   strb r4,[r10]
   sub r10,r10,#240
   cmp r10,r1
   bge moreline

      " :
      /* No output */ :
      "r" (x), "r" (max), "r" (min), "r" (c), "r" (b), "r" (tx), "r" (t), "r" (scale):
      "r9", "r10", "r11");
//=====ENDASM==============*/


All that has changed is the register numbers have been chagned to abide by the rules stated in the documentation. I've added ldmfd sp!,{r5-r8} to set the registers 5-8 from the stack which should be b,tx,t,scale respectively... and I'm asuming r1-r4 are set with x,max,min and c. The extra variables that I'm trying to pass arn't being used just yet they are waiting in r6-r8 until I code the extra stuff. The extra code is going to take the address at t as the 64*64 texture and blit the 'tx' x colum to the screen instead of writting just a solid colour. I know that I don't need c in this case but the code should still work though I've got the extra variables in right?
does anyone have any clue?
thanks again...
_________________
[url="http://www.ice-d.com"]www.ice-d.com[/url]

#8762 - Dev - Sat Jul 19, 2003 6:46 am

Generally speaking, you can't clobber most registers when intermixing C and ASM code.

Precisely which registers must be preserved will depend on your compiler, but for most stuff (including ADS, I believe), R0-R3 are OK to destroy and the rest aren't.

Typically, the other registers are used by the compiler for various purposes -- i.e. R13 is the Stack (duh), R14 is the Return Address, but R12 (or R11, or R10) may be a "stack frame pointer", or a "global variable base" or something else that the compiler expects to be preserved.

I don't have a specific reference, but for ADS you can try looking up "ARM/THUMB Procedure Call Standard" or something similar to that (but equally verbose.) -- or, try "ATPCS".

Take a look at the disassembly of your compiler's generated code when it calls a regular C function that has a bunch of parameters -- also check out the start and end of the function itself.

There will be a small "prologue" and "epilogue" that are placed at the start and end of the function, respectively.

The prologue basically saves the registers that your routine will clobber (except those you're allowed to, of course), then loads the parameters passed from the caller into the registers you want to use.

The epilogue restores the saved registers that were clobbered before returning to the caller.

The only other issue is whether or not your function is supposed to dispose of the passed parameters, or if that's something that the caller is supposed to do.

The compiler has already generated code to push the extra parameters on the stack before calling your function (obviously) -- but it may also have added code that will remove those extra parameters upon return -- which means that your function must NOT remove them before returning!

To find out whether your compiler expects the caller, or the callee, to clean the stack you can simply check the disassembly of the code generated by the compiler when it calls your function.

As an aside, you should also check whether or not your compiler lets you specify which registers the parameters are to be put into -- i.e. Some compilers let you tell them what registers to use, and the compiler takes care of everything else.

Similarly, your compiler may have an option to specify which registers are destroyed by your function, and the compiler will automatically generate all the code to preserve those registers around your function (i.e. it'll create the prologue and epilogue for you, or in some cases, it'll add extra code where your function returns to, that reloads the mangled registers).

Best,

Dev.

#8763 - slip - Sat Jul 19, 2003 7:49 am

ahh crap... fair enough looks like I might have to work on it then. what about if I had an array with all my variables in it then just passed the address to the first entry then I could access the others by incrimenting the address?

I've got the ARM/THUMB Procedure Call Standard, also in the gbaguy tutorials gbaguy talks about the registers you can and can't use. r0-r12 are free to use apparently and r13,r14,and r15 are used for other purposes. I also read this in the document from http://www.geocities.com/wonglinhoo/Arm.htm which explains the use of the r13-r15 in detail.

The document explaining implementing inline asm from gbadev.org explains the format used. The last part is the registers that are "destroyed" (the word used) which are the ones you want to use. I'm guessing that the compiler takes this information and makes a prologue and epilogue as you said.

I'm going to have to call it a day right now and get back to it tomorrow. Thanks for your help everyone and I'll probably be posting tomorrow with more problems... =)...
_________________
[url="http://www.ice-d.com"]www.ice-d.com[/url]

#8764 - Dev - Sat Jul 19, 2003 9:52 am

I checked www.arm.com and found this:

http://www.arm.com/support/566FQ9/$File/ATPCS.pdf

It seems to be from Oct. 2000 -- whether or not this "standard" is still adhered to is anyone's guess.

Checking the first couple pages, you'll see that they refer to stack frame pointers, etc. etc. etc. beyond just R13-R15 -- again, whether or not the other registers are actually used (or were used, or still are), is unknown.

Also, it's probably only "guaranteed" for their own stuff -- i.e. if you're not using ADS, what you need to do could be completely different.

... at least now, though, you'll have a better idea of what to do!

Dev.

#8766 - torne - Sat Jul 19, 2003 12:20 pm

Read my post: http://forum.gbadev.org/viewtopic.php?t=1119
It explains the procedure call standard, more or less. I don't use inline asm, so I do not know what the compiler generates for you.

As a summary, though, you may only change the values of r0-r3, and r11. Other changed values must be pushed to the stack and popped back. If the compiler does this for you, then you won't have to.

To load your parameters, you want to do ldmia sp,{r4-r7}. The stack is indeed full-descending, but you are not popping values from the stack; just reading them. You also do not want to use ! as you don't want to change the stack pointer.

Dev: yes, the current procedure call standard is from October 2000. It just hasn't changed since them. Every single ARM-targetting compiler, linker, or any binary tool should generate code compliant with that standard, including GCC and the ARM SDT. Not all of the standard applies to the GBA though. Section 4 - Base Standard all applies, except for 4.6 and 4.7 (the GBA uses the no floating-point hardware version in 4.8). 5.1 applies if you are mixing ARM and Thumb code, but not the rest of section 5. Section 6 is irrelevant, but section 7 has useful stuff. =)

The GBA doesn't use the stack limit register, but can use the frame pointer register.

Every platform whose compilers are compatible, and every platform with an operating system, has a coherent procedure call standard. It is not an artifact of the compiler you are using; it is an artifact of the platform, and all compiler writers will follow it.

Torne

#8768 - sgstair - Sat Jul 19, 2003 1:41 pm

I think you're trying to approach this the wrong way, when you use the asm keyword from c, and specify certain values for input, you have to access them differently ... (/me goes and looks it up) ...

you might find this useful: http://www.devrs.com/gba/files/asmc.txt

Code:
   asm volatile("
      mov    r3,%0

      mov    r5, #240
      lsl    r5, r5, #1          @ r5 = 480

      mul    r5,r5,r3
      mov    r4,%1
      add    r5,r5,r4
      add    r5,r5,r4

      mov    r3,#192
      lsl    r3, r3, #19         @ r3 = 0x6000000

      add    r3,r3,r5
      mov    r4,%2
      strh   r4,[r3]
      " :
      /* No output */ :                 // No output is returned from this routine.
      "r" (py), "r" (px), "r" (colr) :  // Define the routine inputs (%0,%1,%2).
      "r3", "r4", "r5" );               // Specific which registers we destroy.
                                        // For more info on 'asm' read the GCC docs at gnu.org
   }


When using the asm(), and you specify the inputs, you have to access them using %0, %1, ... instead of trying to pick registers for them - gcc does the register picking and setup. Also, in the 'destroyed', you should list ALL registers you use (write stuff to)

Hope this helps :)
-Stephen

#8769 - sgstair - Sat Jul 19, 2003 1:44 pm

torne wrote:
Read my post: http://forum.gbadev.org/viewtopic.php?t=1119
It explains the procedure call standard, more or less. I don't use inline asm, so I do not know what the compiler generates for you.

As a summary, though, you may only change the values of r0-r3, and r11. Other changed values must be pushed to the stack and popped back. If the compiler does this for you, then you won't have to.

To load your parameters, you want to do ldmia sp,{r4-r7}. The stack is indeed full-descending, but you are not popping values from the stack; just reading them. You also do not want to use ! as you don't want to change the stack pointer.

Torne


This works very nicely when writing the entire function in asm, but when you have an inline asm within C, the C part of the function handles the paramater passing. You will have to either write the entire function in asm (it's not too hard) or just do things the way gcc does them, the asm() keyword has very specific usage for passing paramaters.

-Stephen

#8789 - slip - Sun Jul 20, 2003 3:16 am

torne wrote:
Read my post: http://forum.gbadev.org/viewtopic.php?t=1119
It explains the procedure call standard, more or less. I don't use inline asm, so I do not know what the compiler generates for you.

As a summary, though, you may only change the values of r0-r3, and r11. Other changed values must be pushed to the stack and popped back. If the compiler does this for you, then you won't have to.

To load your parameters, you want to do ldmia sp,{r4-r7}. The stack is indeed full-descending, but you are not popping values from the stack; just reading them. You also do not want to use ! as you don't want to change the stack pointer.

Dev: yes, the current procedure call standard is from October 2000. It just hasn't changed since them. Every single ARM-targetting compiler, linker, or any binary tool should generate code compliant with that standard, including GCC and the ARM SDT. Not all of the standard applies to the GBA though. Section 4 - Base Standard all applies, except for 4.6 and 4.7 (the GBA uses the no floating-point hardware version in 4.8). 5.1 applies if you are mixing ARM and Thumb code, but not the rest of section 5. Section 6 is irrelevant, but section 7 has useful stuff. =)

The GBA doesn't use the stack limit register, but can use the frame pointer register.

Every platform whose compilers are compatible, and every platform with an operating system, has a coherent procedure call standard. It is not an artifact of the compiler you are using; it is an artifact of the platform, and all compiler writers will follow it.

Torne


After reading your other post http://forum.gbadev.org/viewtopic.php?t=1119
I've become a little confused about how you are suposed to push the registers r4-r12 onto the stack but then also be able to load the parameters from the stack as well.
For example r4-r10 I would like to use... so
stmfd sp!,{r4-r10}
I store them on the register so I can restore them later... but I also want to load my 5th to 8th parameter from the stack.
ldmia sp,{r4-r7}
which I worked out that it should be...
ldmia sp+28,{r4-r7}
in order to be pointing to the start of the first parameter. But how can you do this? Should I be using a register so I can load the r13 (sp) then add 28 to it and use that temporary register as the base register?
You guys have been a great help and I'm really starting to understand whats going on. Thanks =)
_________________
[url="http://www.ice-d.com"]www.ice-d.com[/url]

#8790 - slip - Sun Jul 20, 2003 3:30 am

sgstair I read the asmc document and thats how I got started with all this. The problem is that document doesn't talk about passing many parameters. I have some variations of code some work others don't... This is what I have:

Code:

   asm("   
      .ALIGN
      .ARM

   stmfd sp!,{r4-r10}

    mov r4,%4
    mov r3,%3
   mov r2,%2
   mov r1,%1
   mov r0,%0

   mov r8,#240
   mul r9,r1,r8
   add r9,r9,r4
   add r9,r0,r9

   mul r10,r2,r8
   add r0,r0,r4
   add r0,r0,r10

moreline:
   strb r3,[r9]
   sub r9,r9,#240
   cmp r9,r0
   bge moreline

   ldmfd sp!,{r4-r10}

      " :
      /* No output */ :
      "r" (x), "r" (max), "r" (min), "r" (c), "r" (b), "r" (tx):
      "r8", "r9", "r10");


This one works fine.
The difference is at the start in this one. I have done what I said in my previous post about using a temp reg and the sp+28. It works too. But if I remove the any of the lines mov rx,%x in either of these two the routine wont work. It seems that I have to mov r0-r4,%0-%4 as though the parameters arn't being put in r0-r3

Code:

   stmfd sp!,{r4-r10}
   mov r4,r13
   add r4,r4,#28
        ldmia r4,{r4-r8}

    mov r4,%4
    mov r3,%3
   mov r2,%2
   mov r1,%1
   mov r0,%0

.... same as above

   ldmfd sp!,{r4-r10}

      " :
      /* No output */ :
      "r" (x), "r" (max), "r" (min), "r" (c), "r" (b), "r" (tx):
      "r8", "r9", "r10");


The other two variations are the same as above except the difference is the line
"r" (x), "r" (max), "r" (min), "r" (c), "r" (b), "r" (tx):
is extended to
"r" (x), "r" (max), "r" (min), "r" (c), "r" (b), "r" (tx), "r" (t), "r" (scale):

once these extra parameters are included the routine does not work.

Thats the details of my problem.
[/code]
_________________
[url="http://www.ice-d.com"]www.ice-d.com[/url]

#8792 - sgstair - Sun Jul 20, 2003 6:25 am

slip wrote:
sgstair I read the asmc document and thats how I got started with all this. The problem is that document doesn't talk about passing many parameters. I have some variations of code some work others don't... This is what I have:

...

This one works fine.
The difference is at the start in this one. I have done what I said in my previous post about using a temp reg and the sp+28. It works too. But if I remove the any of the lines mov rx,%x in either of these two the routine wont work. It seems that I have to mov r0-r4,%0-%4 as though the parameters arn't being put in r0-r3
...
The other two variations are the same as above except the difference is the line
"r" (x), "r" (max), "r" (min), "r" (c), "r" (b), "r" (tx):
is extended to
"r" (x), "r" (max), "r" (min), "r" (c), "r" (b), "r" (tx), "r" (t), "r" (scale):

once these extra parameters are included the routine does not work.

Thats the details of my problem.
[/code]


Well, quite obviously the paramaters aren't being put in r0-r3! You aren't actually defining your function in ASM, you're just writing an inline section of ASM within a C function. C handles ALL of the paramater passing, and thus the paramaters don't appear at all in your inline block.
using the %0-%4 is the proper way to use paramaters in an inline block.

Another potential problem is you're not defining all of the 'destroyed' variables. you should add to the 3rd varlist (the "r8", "r9", "r10") all of the variables you write to.

If I were you I'd have written the whole routine in pure assembly a long time ago, without worrying about a C function framework :)

-Stephen
_________________
http://blog.akkit.org/ - http://www.akkit.org/dswifi/

#8795 - slip - Sun Jul 20, 2003 8:05 am

I'm happy to write it in pure asm. But I don't know how to use parameters that way, and I'm not sure how to compile and link and include it. I'll still be able to call it from C the same way right?
_________________
[url="http://www.ice-d.com"]www.ice-d.com[/url]

#8800 - torne - Sun Jul 20, 2003 2:33 pm

sgstair is right; if you are going to write inline you should do what the gcc docs say. It's not hard to use a separate file for yous asm tho so maybe you should try that.

Oh, and yes, to get your params, push modified regs, add the size of what you pushed to sp, and load from there.

#8802 - Paul Shirley - Sun Jul 20, 2003 2:52 pm

removed

Last edited by Paul Shirley on Sun Mar 28, 2004 10:07 pm; edited 1 time in total

#8817 - sgstair - Sun Jul 20, 2003 9:11 pm

slip wrote:
I'm happy to write it in pure asm. But I don't know how to use parameters that way, and I'm not sure how to compile and link and include it. I'll still be able to call it from C the same way right?


Yes you could still be able to call it the same way. Using the paramaters isn't too hard either - it's the way described by everyone else around here :)

Here's a snippet of code that uses more than 4 paramaters:

Code:
@extern void DrawPartialImage(s32 x, s32 y, u32 imgnum, u32 orientation,s32 clipx1,s32 clipy1,s32 clipx2,s32 clipy2) {
   @ wanted r0=x, r1=y, r2,imgnum, r3=orientation, r4=clipx1, r5=clipy1,
   @ r6=clipx2, r7=clipy2
DrawPartialImage:   @ expected: r0=x, r1=y, r2=imgnum, r3=orientation, others on stack

   mov      r12,r13 @ save stack
   STMFD   r13!, {r4-r11} @give us all registers to work with (stored 8x4bytes)
   LDMIA   r12,{r4-r7} @clip values x1,y1,x2,y2 in order

... code and more code

DPI_exit:   
   LDMFD r13!,{r4-r11}
   bx lr


I hope that gives you an idea of what to do - if you have more questions I'll try to answer them :)

-Stephen
_________________
http://blog.akkit.org/ - http://www.akkit.org/dswifi/

#8832 - slip - Mon Jul 21, 2003 8:39 am

Hey thats cool.. Thanks.. I've just made a file named tline.s and it looks like this:

Code:

@extern void drawLine(u32 x, u32 max, u32 min, u32 c, u32 b, u32 tx, u32 *t, u32 scale) {
   @ wanted r0=x, r1=max, r2,min, r3=c, r4=b, r5=tx,
   @ r6=*t, r7=scale
drawLine:   @ expected: r0=x, r1=max, r2=min, r3=c, others on stack

   mov     r12,r13 @ save stack
   STMFD   r13!, {r4-r11} @give us all registers to work with (stored 8x4bytes)
   LDMIA   r12,{r4-r7} @clip values b,tx,*t,scale in order

   mov r8,#240
   mul r9,r1,r8
   add r9,r9,r4
   add r9,r0,r9

   mul r10,r2,r8
   add r0,r0,r4
   add r0,r0,r10

moreline:
   strb r3,[r9]
   sub r9,r9,#240
   cmp r9,r0
   bge moreline

DRAWLINE_exit:
   LDMFD r13!,{r4-r11}
   bx lr



=)... to compile it I'm just using my usual:
g++ -c -o tline.o tline.s
and it compiles without any worry. But when I try and link I get:
undefined reference to 'drawLine(unsigned long... more unsigned longs)'
thats coming from my c++ object file. I've included in my header file

extern void drawLine(u32 x, u32 max, u32 min, u32 c, u32 b, u32 tx, u32 *t, u32 scale);

and not sure what to do now. This seems a much more controlable way of doing this. I know where my parameters are now. Its just that undefined reference problem.[/code]
_________________
[url="http://www.ice-d.com"]www.ice-d.com[/url]

#8835 - Quirky - Mon Jul 21, 2003 10:22 am

I'm pretty sure you need to add these lines to the .s to make it global:

.global drawLine
.type drawLine,function

#8837 - slip - Mon Jul 21, 2003 10:34 am

I added

.ARM
.ALIGN
.global drawLine
.type drawLine,function

I forgot to add .ARM and .ALIGN. After adding that though I still had the same linker error. I downloaded the graphics lib from devrs.com and checked out the way the asm was used. It looks like this...

Code:


@ Draw an outline ellipse in GBA graphics modes 3 or 5 in ARM asm
@ (void) gfxEllipse (u8 x, u8 y, u8 xr, u8 yr, u16 color, u32 addr);

        .ARM
        .ALIGN
        .GLOBL  gfxEllipse

gfxEllipse:

...



I've guessed that case is not a problem. And I've even tried the same way as its done in the lib. except I use drawLine. But I still get the link error. =\[/code]
_________________
[url="http://www.ice-d.com"]www.ice-d.com[/url]

#8847 - sgstair - Mon Jul 21, 2003 6:19 pm

Do make sure you're including the .o file generated in your link process!

I think that's your only problem :)

-Stephen
_________________
http://blog.akkit.org/ - http://www.akkit.org/dswifi/

#8857 - slip - Tue Jul 22, 2003 12:21 am

I thought of that... this is what my link batch file looks like.

PATH=C:\devkitadv\bin
g++ -o main.elf *.o -lm
objcopy -O binary main.elf ROm.gba
pause

tline.o is in the directory and I get the error. I just tried adding tline.o after *.o and I got multiple definition drawLine.

...
...

Ok I just tried to compile pixel.s (from the asm gfxlib at devrs.com) into my project then call it and got the same error. I'm guessing that its not the asm its the way I'm compiling and/or linking it?
_________________
[url="http://www.ice-d.com"]www.ice-d.com[/url]