I'm trying to implement an example from a book of calling an assembly function from C. But I keep getting a fatal error where the PC = fffffffe and therefore executing code outside of RAM or ROM.
Here is my C file, t.c:
int g; // uninitialized global
int main()
{
int a, b, c, d, e, f; // local variables
a = b = c = d = e = f = 1; // values do not matter
g = sum(a,b,c,d,e,f); // call sum(), passing a,b,c,d,e,f
}
My assembly file, ts.s:
.global start, sum
start: ldr sp, =stack_top
bl main // call main() in c
stop: b stop
sum: // int sum(int a,b,c,d,e,f) { return a+b+c+d+e+f; }
// upon entry, stack top contains e, f, passed by main() in C
// Establish stack frame
stmfd sp!, {fp, lr} // push fp, lr
add fp, sp, #4 // fp -> saved lr on stack
// Compute sum of all (6) parameters
add r0, r0, r1 // first 4 parameters are in r0-r1
add r0, r0, r2
add r0, r0, r3
ldr r3, [fp, #4] // load e into r3
add r0, r0, r3 // add to sum in r0
ldr r3, [fp, #8] // load f into r3
add r0, r0, r3 // add to sum in r0
// Return to caller
sub sp, fp, #4 // sp=fp-4 (point at saved FP)
ldmfd sp!, {fp, pc} // return to caller
Here is the linker script, t.ld:
ENTRY(start) /* define start as the entry address */
SECTIONS /* program sections */
{
. = 0x10000; /* loading address, required by QEMU */
.text : { *(.text) } /* all text in .text section */
.data : { *(.data) } /* all data in .data section */
.bss : { *(.bss) } /* all bss in .bss section */
. =ALIGN(8);
. =. + 0x1000; /* 4 KB stack space */
stack_top =.; /* stack_top is a symbol exported by linker */
}
I assemble the files using the following:
arm-none-eabi-as -o ts.o ts.s
arm-none-eabi-gcc -c t.c
arm-none-eabi-ld -T t.ld -o t.elf t.o ts.o
arm-none-eabi-objcopy -O binary t.elf t.bin
Then execute with:
qemu-system-arm -M versatilepb -kernel t.bin -nographic -serial /dev/null
Here is the output:
QEMU 2.5.0 monitor - type 'help' for more information
(qemu) pulseaudio: set_sink_input_volume() failed
pulseaudio: Reason: Invalid argument
pulseaudio: set_sink_input_mute() failed
pulseaudio: Reason: Invalid argument
qemu: fatal: Trying to execute code outside RAM or ROM at 0xfffffffe
R00=fffffffc R01=ffffffff R02=00000000 R03=ffffffff
R04=00000000 R05=00000000 R06=00000000 R07=00000000
R08=00000000 R09=00000000 R10=00000000 R11=ffffffff
R12=00000000 R13=42fffff0 R14=00010060 R15=fffffffe
PSR=400001f3 -Z-- T svc32
s00=00000000 s01=00000000 d00=0000000000000000
s02=00000000 s03=00000000 d01=0000000000000000
s04=00000000 s05=00000000 d02=0000000000000000
s06=00000000 s07=00000000 d03=0000000000000000
s08=00000000 s09=00000000 d04=0000000000000000
s10=00000000 s11=00000000 d05=0000000000000000
s12=00000000 s13=00000000 d06=0000000000000000
s14=00000000 s15=00000000 d07=0000000000000000
s16=00000000 s17=00000000 d08=0000000000000000
s18=00000000 s19=00000000 d09=0000000000000000
s20=00000000 s21=00000000 d10=0000000000000000
s22=00000000 s23=00000000 d11=0000000000000000
s24=00000000 s25=00000000 d12=0000000000000000
s26=00000000 s27=00000000 d13=0000000000000000
s28=00000000 s29=00000000 d14=0000000000000000
s30=00000000 s31=00000000 d15=0000000000000000
FPSCR: 00000000
Aborted (core dumped)
I am new to ARM assembly, so I'm not sure how the PC gets all the way to fffffffe. Any help would be appreciated, thank you!
So I've simplified both the C and asm file but still keep getting a fatal error.
Here is the updated C file:
int g; // uninitialized global
int main()
{
g = sum();
}
The ASM file:
.global start, sum
start: ldr sp, =stack_top
bl main // call main() in c
stop: b stop
sum:
push {lr}
pop {pc}
The linking script is the same as before. I still get the following error:
QEMU 2.5.0 monitor - type 'help' for more information
(qemu) pulseaudio: set_sink_input_volume() failed
pulseaudio: Reason: Invalid argument
pulseaudio: set_sink_input_mute() failed
pulseaudio: Reason: Invalid argument
qemu: fatal: Trying to execute code outside RAM or ROM at 0xfffffffe
R00=00000000 R01=00000183 R02=00000100 R03=00000000
R04=00000000 R05=00000000 R06=00000000 R07=00000000
R08=00000000 R09=00000000 R10=00000000 R11=43000004
R12=00000000 R13=43000000 R14=0001000c R15=fffffffe
PSR=400001f3 -Z-- T svc32
s00=00000000 s01=00000000 d00=0000000000000000
s02=00000000 s03=00000000 d01=0000000000000000
s04=00000000 s05=00000000 d02=0000000000000000
s06=00000000 s07=00000000 d03=0000000000000000
s08=00000000 s09=00000000 d04=0000000000000000
s10=00000000 s11=00000000 d05=0000000000000000
s12=00000000 s13=00000000 d06=0000000000000000
s14=00000000 s15=00000000 d07=0000000000000000
s16=00000000 s17=00000000 d08=0000000000000000
s18=00000000 s19=00000000 d09=0000000000000000
s20=00000000 s21=00000000 d10=0000000000000000
s22=00000000 s23=00000000 d11=0000000000000000
s24=00000000 s25=00000000 d12=0000000000000000
s26=00000000 s27=00000000 d13=0000000000000000
s28=00000000 s29=00000000 d14=0000000000000000
s30=00000000 s31=00000000 d15=0000000000000000
FPSCR: 00000000
Aborted (core dumped)
It has something to do with PUSH and POP. Replacing those two with MOV PC,LR the program runs and get no error.
strap.s
.globl _start
_start:
mov sp,#0x10000
bl main
hang:
b hang
.globl sum
sum:
stmfd sp!, {fp, lr} // push fp, lr
add fp, sp, #4 // fp -> saved lr on stack
// Compute sum of all (6) parameters
add r0, r0, r1 // first 4 parameters are in r0-r1
add r0, r0, r2
add r0, r0, r3
ldr r3, [fp, #4] // load e into r3
add r0, r0, r3 // add to sum in r0
ldr r3, [fp, #8] // load f into r3
add r0, r0, r3 // add to sum in r0
// Return to caller
sub sp, fp, #4 // sp=fp-4 (point at saved FP)
ldmfd sp!, {fp, pc} // return to caller
notmain.c
int sum ( int, int, int, int, int, int );
int g; // uninitialized global
int main()
{
int a, b, c, d, e, f; // local variables
a = b = c = d = e = f = 1; // values do not matter
g = sum(a,b,c,d,e,f); // call sum(), passing a,b,c,d,e,f
}
/* memmap */
MEMORY
{
ram : ORIGIN = 0x00010000, LENGTH = 32K
}
SECTIONS
{
.text : { *(.text*) } > ram
.bss : { *(.text*) } > ram
}
arm-linux-gnueabi-as --warn --fatal-warnings -march=armv5t strap.s -o strap.o
arm-linux-gnueabi-gcc -c -Wall -O2 -nostdlib -nostartfiles -ffreestanding -march=armv5t notmain.c -o notmain.o
notmain.c: In function ‘main’:
notmain.c:11:1: warning: control reaches end of non-void function [-Wreturn-type]
}
^
arm-linux-gnueabi-ld strap.o notmain.o -T memmap -o notmain.elf
arm-linux-gnueabi-objdump -D notmain.elf > notmain.list
arm-linux-gnueabi-objcopy notmain.elf -O binary notmain.bin
00010000 <_start>:
10000: e3a0d801 mov sp, #65536 ; 0x10000
10004: eb00000b bl 10038 <main>
00010008 <hang>:
10008: eafffffe b 10008 <hang>
0001000c <sum>:
1000c: e92d4800 push {fp, lr}
10010: e28db004 add fp, sp, #4
10014: e0800001 add r0, r0, r1
10018: e0800002 add r0, r0, r2
1001c: e0800003 add r0, r0, r3
10020: e59b3004 ldr r3, [fp, #4]
10024: e0800003 add r0, r0, r3
10028: e59b3008 ldr r3, [fp, #8]
1002c: e0800003 add r0, r0, r3
10030: e24bd004 sub sp, fp, #4
10034: e8bd8800 pop {fp, pc}
00010038 <main>:
10038: e3a03001 mov r3, #1
1003c: e52de004 push {lr} ; (str lr, [sp, #-4]!)
10040: e24dd00c sub sp, sp, #12
10044: e1a02003 mov r2, r3
10048: e58d3004 str r3, [sp, #4]
1004c: e58d3000 str r3, [sp]
10050: e1a01003 mov r1, r3
10054: e1a00003 mov r0, r3
10058: ebffffeb bl 1000c <sum>
1005c: e59f200c ldr r2, [pc, #12] ; 10070 <main+0x38>
10060: e5820000 str r0, [r2]
10064: e1a00003 mov r0, r3
10068: e28dd00c add sp, sp, #12
1006c: e49df004 pop {pc} ; (ldr pc, [sp], #4)
10070: 00010074 andeq r0, r1, r4, ror r0
Disassembly of section .bss:
00010074 <g>:
10074: 00000000 andeq r0, r0, r0
run it. ctrl-a then x to exit
qemu-system-arm -M versatilepb -m 128M -nographic -kernel notmain.bin
pulseaudio: pa_context_connect() failed
pulseaudio: Reason: Connection refused
pulseaudio: Failed to initialize PA contextaudio: Could not init `pa' audio driver
QEMU: Terminated
no faults.
arm-none-eabi-as --warn --fatal-warnings -march=armv5t strap.s -o strap.o
arm-none-eabi-gcc -c -Wall -O2 -nostdlib -nostartfiles -ffreestanding -march=armv5t notmain.c -o notmain.o
notmain.c: In function ‘main’:
notmain.c:11:1: warning: control reaches end of non-void function [-Wreturn-type]
}
^
arm-none-eabi-ld strap.o notmain.o -T memmap -o notmain.elf
arm-none-eabi-objdump -D notmain.elf > notmain.list
arm-none-eabi-objcopy notmain.elf -O binary notmain.bin
again no faults.
What are the missing parts to your example that you didnt provide?
you can simplify your assembly a little bit if you care to, I can understand why to use the stack frame if you feel the need.
.globl sum
sum:
push {r3,lr}
add r0, r0, r1
add r0, r0, r2
add r0, r0, r3
ldr r3, [fp, #0x08]
add r0, r0, r3
ldr r3, [fp, #0x0C]
add r0, r0, r3
pop {r3,pc}
User contributions licensed under CC BY-SA 3.0