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 > problem accessing variables declared in a function

#12782 - shadow_gg - Wed Nov 26, 2003 11:56 am

hello everybody,
got some noob question:

why this work:
u16 *sky=(u16 *)(0x8000000+SIZE_ROM+SIZE_PAL+SIZE_IMAGE+SIZE_MAP);
void blit_asm()
{

asm volatile("
.ALIGN
.ARM
ldr r0,=screen
ldr r0,[r0] @r0 vram
ldr r3,=sky
ldr r3,[r3] @r3 image
mov r1,#0
ldr r2,=9600
boucle:
ldr r1,[r3],#4
str r1,[r0],#4
subs r2,r2,#1
bpl boucle
bx lr
.pool
":/*no output*/:/*no_input*/:"r0","r1","r2");
}
it compiles fine
but when I put the variable sky in the function,it don't compiles anymore
:(
it doesn't found sky
what is the problem ?
thx for helping me !

#12787 - poslundc - Wed Nov 26, 2003 4:11 pm

Your question is unclear... but I think you are asking why you can no longer reference the variable sky if instead of making it a global variable you make it a local variable in the function.

First of all, you need to realize that there are no "variables" in assembler. When you use the name "sky" in assembler, it is just inserting the memory address of your global variable, which it gets from the linker.

The linker knows the symbol "sky" because it is a global variable. The linker doesn't know the symbols of any local variables in functions.

If you want to use a local variable, you need to pass it as an input to the asm function. See the article on GCC Inline Assembly Rules of Engagement.

Dan.

#12792 - shadow_gg - Wed Nov 26, 2003 5:52 pm

thx but I cannot access yet to local variables even declaring them as operand of asm function.
like this:
void blit_asm()
{
u16 *sky=(u16 *)(0x8000000+SIZE_ROM+SIZE_PAL+SIZE_IMAGE+SIZE_MAP);

asm volatile("
.ALIGN
.ARM
ldr r0,=screen
ldr r0,[r0] @r0 vram
ldr r3,=sky
ldr r3,[r3] @r3 image
ldr r2,=9600
boucle:
ldr r1,[r3],#4
str r1,[r0],#4
subs r2,r2,#1
bpl boucle
bx lr
.pool
":/*no output*/:"m"(sky):"r0","r1","r2");
}
thats means I must pass sky as argument of the function for accessing it?
or declaring the variable directly in the asm block ?
is there a way to accessing a local variable declared in a C funtion in a asm block who is inside this same function ?

sorry for my bad english :/
thx for all

#12802 - DekuTree64 - Wed Nov 26, 2003 8:24 pm

I think you'd need to put "r"(sky) instead of "m", and then use ldr r3, %0, which means the first argment for that ASM block. I haven't messed with inline ASM enough to know the details of it.
I'd suggest just writing the function in pure ASM. Much cleaner and less confusing. Just look around in this section for ASM beginner posts, I've explained how to set up a basic ASM function enough times already^_^
_________________
___________
The best optimization is to do nothing at all.
Therefore a fully optimized program doesn't exist.
-Deku

#12806 - poslundc - Wed Nov 26, 2003 8:44 pm

Once again, please read the rules of engagement article, as they are very clear on how to do this. You do not reference the "sky" variable directly, you need to use the "%" specifier as well as a number specifying which parameter. Using "m" should be correct, though, the way you are using it. (My understanding is that "r" loads it directly into one of the registers, so you wouldn't need the ldr statement, but how does it choose which register? Is it just any register that isn't specified in the clobber list?)

I will also chime in to agree with DekuTree64 that it is much easier to write separate asm files and call the functions from C. It also helps to keep your code understandable as your project gets larger: I have one directory for C files and another for ASM files, and my makefile has separate directives to process the two.

Dan.

#12812 - shadow_gg - Thu Nov 27, 2003 1:45 am

thx u all
it worked well now ^^