linux简单之美
话说windows也有syscall，这是必须的。但是win的syscall可以直接call吗？可以是
可以但是破费周折，搞成SDT之类的复杂概念。下面看看linux是如何做的吧。

view plaincopyprint?

section.data
msgdb&quot;hellohopy!&quot;,0x0a

section.text
global_start

_start:
moveax,4
movebx,1
movecx,msg
movedx,12
int0x80

moveax,1
movebx,0
int0x80


  关键是系统调用号要知道，开始找的是usr/include/asm-gen*/unistd.h，
可是都不对。后来找的是usr/include/x86_64_linux_gnu/asm/下的头文件，
有2个，分别对应x86和x64.、编译连接指令如下:
nasm
Linux 系统调用 汇编
话说windows也有syscall，这是必须的。但是win的syscall可以直接call吗？可以是
可以但是破费周折，搞成SDT之类的复杂概念。下面看看linux是如何做的吧。

view plaincopyprint?

section.data
msgdb&quot;hellohopy!&quot;,0x0a

section.text
global_start

_start:
moveax,4
movebx,1
movecx,msg
movedx,12
int0x80

moveax,1
movebx,0
int0x80


  关键是系统调用号要知道，开始找的是usr/include/asm-gen*/unistd.h，
可是都不对。后来找的是usr/include/x86_64_linux_gnu/asm/下的头文件，
有2个，分别对应x86和x64.、编译连接指令如下:
nasm
![](/data/attachment/album/201406/24/155116x0fq14fe0f909bde.jpeg)


### （一）


话说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的小转换.


via： <http://blog.csdn.net/mydo/article/details/8224352> <http://blog.csdn.net/mydo/article/details/8452386> <http://blog.csdn.net/mydo/article/details/8452417> 

