Linux 简单之美
(一)
话说 windows 也有 syscall,这是必须的。但是 win 的 syscall 可以直接 call 吗?可以是
可以但是破费周折,搞成 SDT 之类的复杂概念。下面看看 linux 是如何做的吧。
section .data msg db "hello hopy!",0x0a section .text global _start _start: mov eax,4 mov ebx,1 mov ecx,msg mov edx,12 int 0x80 mov eax,1 mov ebx,0 int 0x80
关键是系统调用号要知道,开始找的是 usr/include/asm-gen*/unistd.h,
可是都不对。后来找的是 usr/include/x86_64_linux_gnu/asm/下的头文件,
有 2 个,分别对应 x86 和 x64.、编译连接指令如下:
nasm -f elf main.asm ld main.o
运行,段转储错误鸟,查了一下,本猫用的是 x64 位的 linux,所以要生成
x64 位的程序,或者指明是 x86 的程序,我选择后者:
ld -m elf_i386 -o main main.o
哦鸟!
(二)
我们在前一章中看到了如何仅仅用 syscall 做一些简单的事,现在我们看能不能直接调用
C 标准库中的函数快速做一些 复杂 的事:
section .data ft db "now is %d",10 section .text extern puts extern exit extern sleep extern printf global main main: mov edi,11 again: dec edi push edi push ft call printf push 1 call sleep cmp edi,0 jnz again push msg call puts push 0 call exit msg: db "happy xxx day!",0
以上代码功能很简单,从 10 倒数到 0,然后打印一行,最后结束。与之前代码不同的是其中
调用了 C 标准库中的函数。编译和以前一样:
nasm -e elf main.asm
我们看看怎么连接:
gcc -m32 -o main main.o
好鸟!运行正常.
值得注意的是:我的 OS 是 ubuntu64,而 asm 代码中是 32 位的,如果开始用
ld -m elf_i386 -lc -o main main.o
的方式,首先会提示找不到 c 库,这可以进入/usr/lib,然后使用
sudo ln -sv /lib/i386-linux-gun/libc.so.6 libc.so
创建软连接解决.
但在运行时提示无法找到可执行文件!该文件明明在的!
遂用 gcc 来连接,但要将_start 改为 main,还要装载 32 库
sudo apt-get install ia32-libs
还会提示找不到 h 文件,这时再装载库
sudo apt-get install g++-multilib
还有 2 族库,如有必要也可加载:
sudo apt-get install libc6:i386 libgcc1:i386 gcc-4.6-base:i386 libstdc++5:i386 libstdc++6:i386 sudo apt-get install libc6-i386
最后要说的是,一些 C 代码在用 std=c99 编译时会发现提示无法获取结构大小,这时改成如下即可:
gcc -D_GNU_SOURCE -std=c99 main.c
(三)
在(二)中我们尝试使用了 C 库的函数完成功能,那么能不能用 syscall 方式
来搞呢?显然可以!
section .data ft db "now is X",10 section .text global _start _start: mov edi,10 again: dec edi mov eax,edi add eax,0x30 mov byte [ft+7],al mov eax,4 mov ebx,1 mov ecx,ft mov edx,9 int 0x80 mov eax,162 push 0 push 1 mov ebx,esp mov ecx,0 int 0x80 cmp edi,0 jnz again mov eax,4 mov ebx,1 mov ecx,msg mov edx,15 int 0x80 mov eax,1 mov ebx,0 int 0x80 msg: db "happy xxx day!",10
--
nasm -f elf main.asm ld -m elf_i386 -o main main.o
在代码中延时使用的是 nanosleep,其他和第一篇一致,只不过做了一个 bin->ascii 的小转换.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

上一篇: C 编程 Vim 初步配置
下一篇: 彻底找到 Tomcat 启动速度慢的元凶
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论