从 C 调用 ARM 程序集函数时出现致命错误



我正在尝试实现从 C 调用汇编函数的书中的示例。 但是我不断收到一个致命错误,其中PC = fffffffe,因此在RAM或ROM之外执行代码。

这是我的 C 文件,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
}

我的程序集文件,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

下面是链接器脚本 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 */
}

我使用以下方法组装文件:

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

然后执行:

qemu-system-arm -M versatilepb -kernel t.bin -nographic -serial /dev/null

这是输出:

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)

我是ARM组装的新手,所以我不确定PC是如何一路走到fffffffe的。 任何帮助将不胜感激,谢谢!


所以我简化了 C 和 asm 文件,但仍然不断收到致命错误。

这是更新的 C 文件:

int g;      // uninitialized global
int main()
{
g = sum();
}

ASM 文件:

.global start, sum
start:  ldr sp, =stack_top
bl main             // call main() in c
stop:   b stop
sum:
push {lr}
pop  {pc}

链接脚本与以前相同。我仍然收到以下错误:

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)

它与PUSHPOP有关。 用MOV PC,LR替换这两个程序运行并且没有错误。

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

运行它。 按 Ctrl-a 然后 X 退出

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

没有故障。

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

再次没有故障。

您的示例中缺少哪些您没有提供的部分?

如果您愿意,您可以简化您的组装,如果您觉得需要,我可以理解为什么要使用堆栈框架。

.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}

最新更新