1.代码
hello.asm
;编译链接方法
;(ld 的'-s'选项意为“strip all”)
;
;$ nasm -f elf hello.asm -o hello.o
;$ ld -s hello.o -o hello
;$./hello
;Hello,OS
;$
[section .data];数据在此
strHellodb"Hello, world",0Ah
STRLENequ$ - strHello
[section .text];代码在此
global _start;必须导出_start这个入口,以便让链接器识别
_start:
movedx,STRLEN
movecx,strHello
movebx,1
moveax,4;sys_write
int0x80;系统调用
movebx,0
moveax,1;sys_exit
int0x80;系统调用
2.编译链接
> ls
hello.asm
> nasm -f elf64 hello.asm -o hello.o
> ls
hello.asm hello.o
> ld -s hello.o -o hello
> ls
hello hello.asm hello.o
3.执行
> ./hello
Hello,world
4.代码解释
equ:表达式赋值操作符,在某些时候程序中多次出现同一个表达式,为方便起见,用赋值伪操作给表达式赋予一个名字。
int 0x80:系统调用是一个软中断,中断号是0x80,它是上层应用程序与Linux系统内核进行交互通信的唯一接口。通过int 0x80,就可使用内核资源。系统调用是通过int 0x80来实现的,eax寄存器中为调用的功能号,ebx、ecx、edx、esi等等寄存器则依次为参数,exit的功能号_NR_exit为1,write(_NR_write)功能号为4,ebx为文件描述符,stdout的文件描述符为1,ecx则为buffer的内存地址,edx为buffer长度。ebx为0表示返回0。
---------//伪操作
汇编程序中以.开头的名称并不是指令的助记符,不会被翻译成机器指令,而是给汇编器一些特殊指示,称为汇编指示或伪操作。
符号在汇编程序中代表一个地址,可以用在指令中,汇编程序经过汇编器的处理之后,所有的符号都被替换成它所代表的地址值。
.section:指示把代码划分成若干个段,程序被操作系统加载执行时,每个段被加载到不同的地址,操作系统对不同的页面设置不同的读、写、执行权限。
.global:告诉汇编器,_start这个符号要被链接器用到,所以要在目标文件的符号表中标记它是一个全局符号,_start就像C程序的main函数一样特殊,是整个程序的入口,链接器在链接时会查找目标文件中的_start符号代表的地址,把它设置为整个程序的入口地址,所以每个汇编程序都要提供一个_start符号并且用.globl声明。如果一个符号没有用.globl声明,就表示这个符号不会被链接器用到。
.data:.data段保存程序的数据,是可读可写的,相当于C的全局变量。
.text:.text段保存代码,是只读和可执行的,后面那些指令都属于这个.text段。
_start:是一个符号。
---------//命令行(分清是谁的选项)
-s:strip,去掉符号表等内容,可起到对生成的可执行代码减肥的功效
ls:列出当前目录下的所有文件
ld:把一定量的目标文件跟档案文件连接起来,并重定位它们的数据,连接符号引用。