Problems Calling Asm From C


Dave18

Member
Joined
Mar 16, 2003
Messages
352
Age
49
I am trying to call an ASM routine from C. The code compiles perfectly but for some reason it does not return from the ASM call (GP2X resets). What I don't get is that I used to call ASM from C all the time on the GP32 without any problems at all and the ASM function here actually works on the GP32 without issue. Grateful if anyone could point me to what the issue is.

C Code
CODE


#include "minimal.h"
#include "main.h"

const int SCREEN_WIDTH = 320;
const int SCREEN_HEIGHT = 240;

int main( int argc, char* args[] )
{

gp2x_init(1000, 16, 11025,16,1,60, 1);


gp2x_printf(NULL,0,10,"Calling AYRESET/n");
gp2x_video_RGB_flip(0);
AYRESET();
gp2x_video_RGB_flip(0);
gp2x_printf(NULL,0,-1,"Back from AYRESET/n");
gp2x_video_RGB_flip(0);

int keydata=0;
while (keydata!=GP2X_X)
{
keydata=gp2x_joystick_read(0);
}

gp2x_deinit();
chdir("/usr/gp2x");
execl("/usr/gp2x/gp2xmenu", "/usr/gp2x/gp2xmenu", NULL);


return 0;
}

void gp2x_sound_frame(void *blah, void *buff, int samples) {}



Header file
CODE

void AYRESET(void);



And the ASM
CODE

.ALIGN
.GLOBAL AYRESET
.TYPE AYRESET,function
.CODE 32

AYRESET:
sub sp,sp,#4
stmfd r13!,{r0-r6,lr}


adrl r1,AYStorage
mov r2,#16 @ Number of locations to set to 0
mov r0,#0

AYRESETLOOP:
str r0,[r1],#4 @ Store 0 to memory
subs r2,r2,#1 @ Decrease counter
bne AYRESETLOOP

add r1,r1,#4
mov r2,#31 @ Number of locations to 0
mov r0,#0
AYRESETLOOP2:
str r0,[r1],#4 @ Store 0 to memory
subs r2,r2,#1 @ Decrease counter
bne AYRESETLOOP2

ldmfd r13!,{r0-r6,lr}
add sp,sp,#4
mov pc,lr @

AYStorage:
.word 0 @ AY_AFINE 0 0
.word 0 @ AY_ACOARSE 1 4
.word 0 @ AY_BFINE 2 8
.word 0 @ AY_BCOARSE 3 12
.word 0 @ AY_CFINE 4 16
.word 0 @ AY_CCOARSE 5 20
.word 0 @ AY_NOISEPER 6 24
.word 0 @ AY_ENABLE 7 28
.word 0 @ AY_AVOL 8 32
.word 0 @ AY_BVOL 9 36
.word 0 @ AY_CVOL 10 40
.word 0 @ AY_EFINE 11 44
.word 0 @ AY_ECOARSE 12 48
.word 0 @ AY_ESHAPE 13 52
.word 0 @ AY_PORTA 14 56
.word 0 @ AY_PORTB 15 60

.word 6520 @ UPDATE STEP 64
@ .word 26080 @ UPDATE STEP


.word 0 @ AYREG = 0 68
.word 0 @ OutputA = 0 72
.word 0 @ OutputB = 0 76
.word 0 @ OutputC = 0 80
.word 0 @ OutputN = 255 84
.word 0 @ PeriodA = 0 88
.word 0 @ PeriodB = 0 92
.word 0 @ PeriodC = 0 96
.word 0 @ PeriodN = 0 100
.word 0 @ PeriodE = 0 104
.word 0 @ CountA = 0 108
.word 0 @ CountB = 0 112
.word 0 @ CountC = 0 116
.word 0 @ CountN = 0 120
.word 0 @ CountE = 0 124
.word 0 @ VolA = 0 128
.word 0 @ VolB = 0 132
.word 0 @ VolC = 0 136
.word 0 @ VolE = 0 140
.word 0 @ EnvelopeA = 0 144
.word 0 @ EnvelopeB = 0 148
.word 0 @ EnvelopeC = 0 152
.word 0 @ CountEnv = 0 156
.word 0 @ Hold = 0 160
.word 0 @ Alt2 = 0 164
.word 0 @ Holding = 0 168
.word 0 @ Attack = 0 172
.word 0 @ RNG=1 176
.word 0 @ AYOUTNOISE = 0 180
.word 0 @ Blank space to hold R0184
.word 0 @ VolA2 188
.word 0 @ VolB2 192
.word 0 @ VolC2 196

.word 1773400 @ AY_CLOCK
.word 32768 @ AY_STEP



AYVOLUME:
.byte 0,0,4,4,4,4,8,8
.byte 12,12,16,16,20,20,36,36
.byte 44,44,68,68,92,92,116,116
.byte 148,148,176,176,216,216,252,252





Obviously Rlyeh's minimal library is also included unchanged. As I said there are no compile errors or warnings at all.

Thanks

Dave
 
What do you use "sub sp,sp,#4" for? and why do you mix sp and r13? That just makes the code harder to read. Decide on one and stick with it.

Secondly, if the gp2x resets, chances are it's fallen into one of the fault vectors. Use gdb to figure out the last instruction executed.
 
Isn't the problem that you're writing to AYStorage which is stored in code section which is non-writable ?
 
Unlike GP32, GP2X runs Linux, which makes code (.text) section readonly, so writes there will crash. Add .DATA before AYStorage to put those tables to read-write data section. Then change
CODE

adrl r1,AYStorage


to
CODE

ldr r1=AYStorage


and it should work.
Can't imagine how this can reset GP2X, though.
 
Thanks that's fixed it. Caused a bit of a nightmare first of all with a load of 'literal constant: pool needs to be closer' errors but then I learned how to put the code into sections which seemed to work nicely (although I haven't looked at the resulting code to see how this has affected how well optimised it is, I'm suspicious it may have added some additional branching).

@Squidge: I was learning ARM assembly when I wrote this code so there's lots of inconsistencies and general bad code which I have never gotten around to tidying up. I guess I moved the stack pointer to give myself a buffer when originally testing to make sure a bug wasn't related to the stack getting overwritten and then never removed it (I wrote the code years ago for the GP32 so can't really remember). I am a very messy coder at the best of times. ;)

Anyway thanks to all for the help.

Dave
 
Dave18 said:
Thanks that's fixed it. Caused a bit of a nightmare first of all with a load of 'literal constant: pool needs to be closer' errors but then I learned how to put the code into sections which seemed to work nicely (although I haven't looked at the resulting code to see how this has affected how well optimised it is, I'm suspicious it may have added some additional branching).
Instead of dividing code into sections, you can use the ".ltorg" assembler directive instead, to get rid of those errors. This is what the assembler uses at the end of sections, that's why dividing code into section gets rid of those errors.
 
Last edited by a moderator:
Back
Top