能否将printf函数以静态形式链接进汇编程序?

weiweishuo 2012-10-02 07:24:07
我在网上搜了很久很久了...因此请各位耐心看。下面两段程序:
test.asm
-------------
[section .text]
global _start
extern hello
_start:
push dword 1234
call hello

hello.c
-------------
int hello(int a){
printf("a is %d",a);
return 0;
}

linux下输入命令:
gcc -c hello.c //成功执行
nasm -f elf -o test.o test.asm//成功执行
ld ld -static -o test test.o hello.o -lc //关键是这一句,输出的错误我不敢全贴出来(太长了),怕把人吓跑了。
----------------------报错--------------------------
/usr/lib/libc.a(syslog.o): In function `closelog':
(.text+0xc9): undefined reference to `_Unwind_Resume'
/usr/lib/libc.a(syslog.o): In function `openlog':
(.text+0x344): undefined reference to `_Unwind_Resume'
/usr/lib/libc.a(syslog.o): In function `__vsyslog_chk':
(.text+0x85a): undefined reference to `_Unwind_Resume'
/usr/lib/libc.a(syslog.o): In function `__vsyslog_chk':
...还有很多很多
---------------------------------------------------------

请高手赐教!
----------------------------------------------------------
我说一点自己的想法:将printf以静态库方式链接进程序,我只能做到一部分,请看下面一段程序:
h.c
---------------------------------------------------------
int main(void){
printf("hello linux");
return 0;
}

linux下输入命令:
gcc -c h.c //执行成功
gcc -static -lc -o h h.o //执行成功
生成的可执行文件h体积是574631字节(显然是链接入了静态库)
但问题是:一旦像上面在汇编文件里用到了_start,gcc就不能参与第二步的链接了,用ld吧,也不行...



...全文
277 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
mLee79 2012-10-08
  • 打赏
  • 举报
回复
你还是不要用汇编写入口函数了, 你的 _start 里没有初始化 C 库, 一运行就 crush ...

这样子链接的:
gcc -m32 -static -o test test.o hello.o -lc -lgcc -lgcc_eh -nostdlib
mLee79 2012-10-08
  • 打赏
  • 举报
回复
gcc -static -o test test.o hello.o
mLee79 2012-10-08
  • 打赏
  • 举报
回复
ld -static -o test test.o hello.o -lc -lgcc -lgcc_eh

或者直接 gcc -o test test.o hello.o
  • 打赏
  • 举报
回复
如果使用mingw移植的gcc,永远无法静态连接glibc的功能(至少我不知道怎么连接),指定-static也不行,它要么动态连接到msvcrt.dll,要么连接到特定版本的ms运行库,比如msvcr100.dll,要么连接到crtdll.dll,取决于连接时使用的库。
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 的回复:]

引用 3 楼 的回复:

引用 2 楼 的回复:

连接c库之后程序入口会在c运行库中,但C运行库会调用main函数。所以test.asm
_start 改为 _main
应该就可以了。

未测试,猜的。

试了一下
test.asm如下
Assembly code
[section .text]
global _main
extern _hello
_ma……
[/Quote]
呃,没linux只是用了mingw的gcc测试过了。
应该还是名字问题, _main 改为 main,再用ld链接 试试。

默认情况下,不管静态链接还是动态链接,入口点都会在c运行库内。就是说asm文件中定义一个等价C的main函数就能通过。
大熊猫侯佩 2012-10-03
  • 打赏
  • 举报
回复
如你所说,加-static
weiweishuo 2012-10-03
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 的回复:]

引用 4 楼 的回复:

引用 3 楼 的回复:

引用 2 楼 的回复:

连接c库之后程序入口会在c运行库中,但C运行库会调用main函数。所以test.asm
_start 改为 _main
应该就可以了。

未测试,猜的。

试了一下
test.asm如下
Assembly code
[section .text]
global _main
ex……
[/Quote]发现asmhello.asm(就是我从网上找到的那段代码)是可以进行静态链接的:
------------------
wws@bogon:~/lab/test$ nasm -f elf asmhello.asm
wws@bogon:~/lab/test$ gcc -static -lc -o asmhello asmhello.o
wws@bogon:~/lab/test$ asmhello
Helloooooo, nurse!
------------------
查看asmhello可执行文件的体积有500多kb,证明静态链接对了
至于我那两段程序,我缓过劲儿再测试,实在累
weiweishuo 2012-10-03
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 的回复:]

引用 2 楼 的回复:

连接c库之后程序入口会在c运行库中,但C运行库会调用main函数。所以test.asm
_start 改为 _main
应该就可以了。

未测试,猜的。

试了一下
test.asm如下
Assembly code
[section .text]
global _main
extern _hello
_main:
push dword 1234……
[/Quote]
在网上找到了一段nasm汇编调用printf的代码,测试成功:
------------
  ; asmhello.asm ========================================================
  global main
  extern printf
  section .data
  msg db "Helloooooo, nurse!",0Dh,0Ah,0
  section .text
  main:
  push dword msg
  call printf
  pop eax
  ret
-------------------
看来我传递的参数个数首先就不对。
_start改成main之后,执行gcc -o t test.o hello.o链接成功(ld没有试)。
但还是那个问题:一旦更换成gcc -static -lc -o t test.o hello.o就出问题,没法儿静态链接...
weiweishuo 2012-10-02
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 的回复:]

不懂,帮顶。
[/Quote]你不会不懂吧,名字起的这有学问:arm前缀,sword还是ELF的约定数据类型...我问的就有elf的问题
weiweishuo 2012-10-02
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 的回复:]

引用 2 楼 的回复:

连接c库之后程序入口会在c运行库中,但C运行库会调用main函数。所以test.asm
_start 改为 _main
应该就可以了。

未测试,猜的。

试了一下
test.asm如下
Assembly code
[section .text]
global _main
extern _hello
_main:
push dword 1234……
[/Quote]我按你说的试了两遍,报错:
wws@bogon:~/lab/test$ gcc -o t test.o hello.o
/usr/lib/gcc/i486-linux-gnu/4.4.5/../../../../lib/crt1.o: In function `_start':
(.text+0x18): undefined reference to `main'
collect2: ld returned 1 exit status

而且,你这样即使执行成功,也不是“静态链接”,而是动态链接的printf函数。
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 的回复:]

连接c库之后程序入口会在c运行库中,但C运行库会调用main函数。所以test.asm
_start 改为 _main
应该就可以了。

未测试,猜的。
[/Quote]
试了一下
test.asm如下
[section .text]
global _main
extern _hello
_main:
push dword 1234
call _hello

最后链接用
gcc -o test test.o hello.o ( ld 不太会用 )
就可以了
  • 打赏
  • 举报
回复
连接c库之后程序入口会在c运行库中,但C运行库会调用main函数。所以test.asm
_start 改为 _main
应该就可以了。

未测试,猜的。
jackyjkchen 2012-10-02
  • 打赏
  • 举报
回复
我只用masm做过,无论动态静态,调用C库无压力

69,375

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧