ARM汇编与C混合编程:printf未定义引用问题求助
Hey there! Let's work through this linker issue you're hitting with your first ARM mixed-code project. I remember stumbling over similar problems when I started with the GNU ARM toolchain, so I totally get the frustration after searching for hours.
What's Causing the Issue?
When you use arm-none-eabi-ld directly to link your objects, adding -lc (the C standard library) isn't enough. Here's why:
printfdoesn't just depend on libc—it also relies on helper functions fromlibgcc(like ARM-specific instruction emulation or stack handling).- You're missing the C runtime startup files (things like
crt0.o) that set up the stack, initialize global variables, and prepare the environment before callingmain. Theldlinker doesn't include these automatically, butarm-none-eabi-gccdoes.
Simple Solution: Use arm-none-eabi-gcc for Linking
Instead of manually invoking ld, let the GCC driver handle the linking process—it will automatically pull in all the required startup files, libraries, and dependencies. Here's how to adjust your commands:
Compile your assembly and C files as before:
arm-none-eabi-gcc -g -c -o multi-arm.o multi.S arm-none-eabi-gcc -g -c -o multi.o multi.cLink using
arm-none-eabi-gccinstead ofld:arm-none-eabi-gcc multi.o multi-arm.o -o multi.elf
That's it! This should resolve both the entry point warning and the printf undefined reference error.
If You Must Use ld (For Learning Purposes)
If you want to understand the manual linking process, you'll need to explicitly include the startup files, libgcc, and libc. You'll have to find the path to your ARM toolchain's library directory (usually something like <toolchain-path>/arm-none-eabi/lib). Then run:
arm-none-eabi-ld --entry main multi.o multi-arm.o -L/path/to/arm-none-eabi/lib -lcrt0 -lgcc -lc -o multi.elf
-lcrt0: Links the C runtime startup code-lgcc: Links the GCC helper library-lc: Links the C standard library
Quick Optimization Tip for Your Assembly Code
Since you're learning ARM assembly, a quick note: your multi function can be simplified using the ARM calling convention (where r0 and r1 hold the first two parameters, and r0 holds the return value). You don't need the frame pointer setup for such a simple function:
.globl multi multi: mul r0, r1, r0 @ Multiply r0 (a) by r1 (b), store result in r0 bx lr @ Return to caller
This does the exact same thing but is much cleaner!
内容的提问来源于stack exchange,提问作者shawnadl

