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 > inline asm

#9235 - johnny_north - Thu Jul 31, 2003 4:36 am

I admit I don't know what I'm doing when it comes to assembly, could someone help me here?

When I do this:

void MBClient::SWI25(MBStruct mp){
asm("mov r0, %0\n"
" mov r1,#1\n"
" swi 0x25\n" //NOTE!!!!! Use 0x250000 for ARM C Compiler mode.
: // Outputs // 0x25 here will only work for Thumb mode.
: // Inputs
: "r0","r1","r2","r8","r9","r10","r11","r12" // Regs crushed & smushed
);

}

I get the error:
mbclient.cpp: In member function `void MBClient::SWI25(MBStruct)':
mbclient.cpp:140: invalid `asm': operand number out of range

I'm trying to take Jeff F's multiboot struct out of the global variable space, instead passing the struct to swi25 as a local. How can I set r0 to mp and avoid this error?

Maybe someone could help me with the main issue: when I declare the MBStruct as a global (MBStruct is just a struct with info for the bios to do multiboot cliet stuff, about 40 bytes) the program starts fine, then hangs in the same place every time. If I make the MBStruct a member of a class and declare an instace of the class, no problem. Any reason declaring a global would do this?

devkit R4, C++
CFLAGS = -I $(INCDIR2) -I $(INCDIR) -I $(PRJDIR) -mthumb-interwork -c -g -Wall
SFLAGS = -I $(INCDIR2) -I $(INCDIR) --warn -mthumb-interwork -marm7tdmi
LDFLAGS = -L $(LIBDIR) -L $(LIBDIR2) -L $(PRJDIR) -T lnkscript -lm -lg -lstdc++ -lgcc -nostartfiles -Wl,-Map,bin.map

#9236 - DekuTree64 - Thu Jul 31, 2003 5:24 am

Put "r" (mp) where it says // Inputs and it should work.
But my advice is to use pure ASM instead of inline, unless absolutely neccessary. Just make a .s file and write functions in that, and call them from C like regular functions.
Basically what you need to do for an ASM function is something like
Code:

.global FuncName
.arm
.align 4
FuncName:
//do stuff
bx lr


Another thnig you'll most likely need is to save registers so you can mess with them, and then restore them before you return, so do something like

Code:

.global AnotherFunction
.arm
.align 4
AnotherFunction:
stmfd sp!, {r4-r7}
//do stuff involving r4-r7
ldmfd sp!. {r4-r7}
bx lr


stm/ldm mean store multiple/load multiple, and fd means full descending Full means the value currently pointed to by the stack pointer (r13, also called sp), is used, so you should change sp before writing to it, or load from it before changing it, and descending means it grows downward, so decrement and then store, or load and then increment.
Hope that helps, just post if anything needs clearing up.

Oh, and I don't know if that would work for a member function, I've never used C++ on GBA. But you could write an ASM function and then call that from your C++ member function.
_________________
___________
The best optimization is to do nothing at all.
Therefore a fully optimized program doesn't exist.
-Deku

#9291 - johnny_north - Fri Aug 01, 2003 2:34 am

I see what you're refering to when I look at other code. Ok, I've made the change:

void MBClient::SWI25(MBStruct mp){

// Execute BIOS routine to transfer client binary to slave unit
asm volatile (
" mov r0, %0\n"
" mov r1,#1\n"
" swi 0x25\n" //NOTE!!!!! Use 0x250000 for ARM C Compiler mode.
: // Outputs // 0x25 here will only work for Thumb mode.
: "r" (mp)// Inputs
: "r0","r1","r2","r8","r9","r10","r11","r12" // Regs crushed & smushed
);

}

Now I get this error:
mbclient.cpp: In member function `void MBClient::SWI25(MBStruct)':
mbclient.cpp:140: Internal compiler error in emit_move_insn, at expr.c:2713 (this is line 140 " mov r0, %0\n")
Please submit a full bug report,
with preprocessed source if appropriate.

I have other swi inline stuff elsewhere that compiles and works fine:

void Background::LZ77UnCompVRAM(u32 source, u32 dest) {
asm("mov r0, %0\n"
"mov r1, %1\n"
"swi 0x12 << 16 \n"
:
:"r" (source), "r" (dest)
:"r0", "r1" );
}

??

#9292 - johnny_north - Fri Aug 01, 2003 2:36 am

I was mistaken the line 140 error refers to:

asm volatile (

#9295 - DekuTree64 - Fri Aug 01, 2003 3:24 am

Try ldr r0, %0 or ldr r0, [%0], forgot which it is, but I think that's the problem.
_________________
___________
The best optimization is to do nothing at all.
Therefore a fully optimized program doesn't exist.
-Deku

#9311 - tom - Fri Aug 01, 2003 10:50 am

no, the problem is something else.
look at the following bit of code (i used this to reproduce the problem, i was so bored=)

Code:

typedef struct {
    u32 x;
    u32 y;
    u32 z;
}bla;

void foo(bla blubb) {
    asm volatile (
        "mov    r0,%0    \n"
        :
        : "r"(blubb)
        : "r0"
    );
}


the problem is, blubb is a bla structure on the stack, and with the line

"r"(blubb)

you tell the compiler to move this structure (not its address, which is probably what you want...) into a register, which isn't possible.
solution: make blubb a pointer to a bla structure.


Code:

void MBClient::SWI25(MBStruct *mp){
    asm(
        "mov r0,%0\n"
        "mov r1,#1\n"
        "swi 0x25\n"
        : // no output
        : "r"(mp)
        : "r0","r1","r2","r8","r9","r10","r11","r12"
    );
}


this should work, haven't tested it, though.
oh yes...something else: according to gbatek, the pointer to the multiboot structure must be passed in r7, not r0. also, there's a return value you might want to pass back (r0 0=okay, 1=failed)