我一直在Mac OS X 10.6上使用GCC 4.6.2.我在编译时使用-static-libgcc选项,否则我的二进制文件在系统上查找libgcc并且我不确定OS X上是否支持GCC 4.2.这样可以正常工作,但为什么我甚至需要libgcc?我读了它并且GNU文档说它包含"目标处理器不能直接执行的算术运算".我怎么知道这些操作是什么?为什么它们如此复杂以至于我需要包含这个库?为什么GCC不能直接优化代码而不必诉诸这些库函数?我有点困惑.对此有任何见解将不胜感激!
我正在尝试在Linux下编译一个C程序.然而,出于好奇,我正在尝试手动执行一些步骤:我使用:
现在我被连接部分困住了.
该程序是一个非常基本的"Hello world":
#include <stdio.h>
int main() {
printf("Hello\n");
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我使用以下命令来生成汇编代码:
gcc hello.c -S -masm=intel
Run Code Online (Sandbox Code Playgroud)
我告诉gcc在编译后退出并使用Intel语法转储汇编代码.
然后我使用GNU汇编程序来生成目标文件:
as -o hello.o hello.s
Run Code Online (Sandbox Code Playgroud)
然后我尝试使用ld生成最终的可执行文件:
ld hello.o /usr/lib/libc.so /usr/lib/crt1.o -o hello
Run Code Online (Sandbox Code Playgroud)
但我不断收到以下错误消息:
/usr/lib/crt1.o: In function `_start':
(.text+0xc): undefined reference to `__libc_csu_fini'
/usr/lib/crt1.o: In function `_start':
(.text+0x11): undefined reference to `__libc_csu_init'
Run Code Online (Sandbox Code Playgroud)
符号__libc_csu_fini/init似乎是glibc的一部分,但我无法在任何地方找到它们!我尝试/usr/lib/libc.a使用相同的结果静态链接libc(反对).
问题是什么?
我编写了可以编译的汇编代码:
as power.s -o power.o
Run Code Online (Sandbox Code Playgroud)
当我链接power.o目标文件时出现问题:
ld power.o -o power
Run Code Online (Sandbox Code Playgroud)
为了在64位操作系统(Ubuntu 14.04)上运行,我.code32在power.s文件的开头添加了,但是我仍然得到错误:
分段故障(核心转储)
power.s:
.code32
.section .data
.section .text
.global _start
_start:
pushl $3
pushl $2
call power
addl $8, %esp
pushl %eax
pushl $2
pushl $5
call power
addl $8, %esp
popl %ebx
addl %eax, %ebx
movl $1, %eax
int $0x80
.type power, @function
power:
pushl %ebp
movl %esp, %ebp
subl $4, %esp
movl 8(%ebp), %ebx
movl 12(%ebp), %ecx
movl %ebx, -4(%ebp)
power_loop_start:
cmpl …Run Code Online (Sandbox Code Playgroud) 我想知道程序是如何工作的,以便尽可能地让它成为一块骨头.
我刚刚发现了如何使用wprintf函数为x86_64汇编代码(发现宽字符是32位).我所要做的只是链接到libc(-lc).
我正在尝试为32位代码组装代码做同样的事情,但我偶然发现了一点.最终我使用gcc进行链接(并将_start:更改为main :).所以我用ld自己做了连接,包括crt1.o crti.o和crtn.o. 然后我的程序工作(之前不打印任何东西)所以我的问题是,我可以在我的代码中做些什么来消除对这些其他3个目标文件的需要(当然还原为_start:而不是main :) ?
test_lib.S
.section .data
locale:
.string ""
.align 4
printformat:
.long '%','l','c',0
.section .text
.global main
main:
pushl $locale
pushl $6
call setlocale
pushl $12414
pushl $printformat
call wprintf
pushl $2
call exit
Run Code Online (Sandbox Code Playgroud)
并运行以下
as --32 test_lib.S -o test_lib.o
ld -m elf_i386 -L/lib/ -L/usr/lib/ -I/lib/ld-linux.so.2 /usr/lib/crt1.o /usr/lib/crti.o -lc /usr/lib/crtn.o test_lib.o -o test_lib
./test_lib
Run Code Online (Sandbox Code Playgroud)
哦,输出只是日本平假名(ma)ま(注意没有换行符,所以它在提示之前打印)