您的位置:首页 > 运维架构 > Linux

hello world linux汇编

2016-03-28 00:29 609 查看
一、Linux汇编介绍

1、DOS和Linux汇编主要不同的地方

DOS汇编中,大部分工作依靠21号中断(int 21h,DOS中断子程序)来完成,并且BIOS服务中断用int 10h(BIOS中断-显示器输出中断调用)和int 16h(BIOS中断-键盘输入中断调用);在linux中,所有的函数通过linux系统调用最终被内核处理,并且通过int 80h陷入内核代替用户空间执行,这称为linux的软中断。linux的系统调用比DOS更少但更实用。

linux是一个32位保护模式编程系统,因此我们能处理真正的现代的32位汇编,32位代码运行在flat(平板)内存模型,其基本意思就是你根本不用再担心段寄存器的处理,因为你不必用段地址来重写或者修改段寄存器,它的每个地址都是32位长,并包含一个偏移量。

x86的32位汇编代码中,你可以使用32位寄存器如eax,ebx,ecx,edx等,来代替16寄存器ax,bx,cx,dx等等。

DOS的16编程时代已经过时了,只有一些不舍得扔下386编程的一些老的黑客仍在用它,linux汇编更实用。(linux操作系统一部分由汇编代码编写,并且硬件驱动也常常离不开汇编代码,因为他是最靠近硬件的语言)

2、一个汇编程序的组成

一个简单的汇编代码通常分成下面三个段:

旁注:在编译器编译并链接生成可执行文件的过程中,会出现两个section的概念——

1)一个是在生成目标文件,通常是我们所说的.o文件,目标文件也是由多个section组成,我们通常叫这个section为“节”,这里的每个section的地址是静态偏移地址,是基于0的偏移地址,而在我们链接多个目标文件(.o)及库(静态库和动态库,关于这两者,详细请看ld手册)时,实际上是经过ld链接脚本的处理并进行重定位之后,

2)把每个目标文件中的各个section放到可执行文件的一个section中,这个section我们通常叫它段(例如.text节重定位之后生成.text段,.data节重定位生成.data段等等),详细请参考ld manual

.data section(节)

这个section主要存放初始化的数据,.data section包含利用像文件名、缓冲大小,并且还可以用EQU定义常量(constant),可以使用的一些指令如:DB,DW,DD,DQ,DT

例:

section .data

message: db ‘Hello world!’ ;相当于char/unsigned char* Hello world!

msglength: equ 12 ; 字符串长度12字节

buffersize: dw 1024 ;缓冲区大小1024个字长(相当于short类型)

.bss section ;未初始化section

;这个section存放未初始化数据,可以用RESB,RESW,RESD,RESQ和REST指令来为你的变量申请为初始化空间。

section .bss

filename: resb 255 ;255字节

number: resb 1

bignum: resw 1

realarray: resq 10

.text section ;代码section

这个section用于存放用户代码,.text section必须从global _start开始,来告诉内核程序从什么地方开始执行(类似于C或JAVA中的main函数,这里指一个开始位置)

section .text

global _start

_start:

pop ebx ;这里是程序实际开始的地方

.

.

.

正如你所看到的,到目前为止,或者多或少都有一点DOS的味道,下面我们通过讲解linux系统调用之后,便可以完成你的第一个linux汇编程序了。

3、linux系统调用

linux系统调用和DOS系统调用并不完全一样:

1. 放系统调用号到eax中

2. 设置系统调用参数到ebx,ecx等

3. 调用相关中断(DOS:21h; linux:80h)

4. 返回结果通常保存在eax中

对于系统调用,x86有6个寄存器可以使用,分别是是ebx,ecx,edx,esi,edi,ebp,如果参数多于6个,ebx必须包含一个参数存放的地址,但我们通常不必担心,因为系统调用不大可能超过6个参数,更为激动的是,linux系统调用设计一贯都遵守这个原则。

下面是一些可能有帮助的例子:

move ax,1 ;sys_exit系统调用号

mov ebx,0 ;exit参数0,相当于exit(0)

int 80h ;80中断,通常中软中断,调用它意思就是告诉内核,你处理它

接下来,你需要知道的是如何知道系统调用是什么,它们什么功能,有几个参数等等?首先,所有的系统调用和对应的系统调用号都可以在/usr/include/asm/unistd.h中找到,在调用int 80h之前,你需要将它们存入eax中。看一看系统调用表,可以看到比如sys_write(4)、sys_nice(34)和sys_exit(1),4、34、1表示对应的系统调用的系统调用号。

4、最简单的程序HELLO WORLD

; hello.asm

section .data ; 数据段声明

msg db "Hello, world!", 0xA ; 要输出的字符串

len equ $ - msg ; 字串长度

section .text ; 代码段声明

global _start ; 指定入口函数

_start: ; 在屏幕上显示一个字符串

;1、设置系统调用号4,采用软中断80可以陷入内核执行

;所有的系统调用和对应的系统调用号都可以在/usr/include/asm/unistd.h中找到

;4号系统调用号为write这个系统调用

mov eax, 4 ; 系统调用号(sys_write)

;2、设置系统调用参数

;man 2 write 可以查看write系统调用的功能

;write函数原型: ssize_t write(int fd,const void *buf,size_t count);

mov ebx, 1 ; 参数一:文件描述符(stdout)

mov ecx, msg ; 参数二:要显示的字符串

mov edx, len ; 参数三:字符串长度

int 0x80 ; 调用内核功能。软中断,陷入内核

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

; 退出程序

;3、设置系统调用号1,采用软中断80可以陷入内核执行

mov eax, 1 ; 系统调用号(sys_exit)

;4、设置系统调用参数

mov ebx, 0 ; 参数一:退出代码

int 0x80 ; 调用内核功能

编译和运行方法:

[hadoop@sam1 test_sam]$ ls

hello.asm

[hadoop@sam1 test_sam]$ nasm -f elf hello.asm

[hadoop@sam1 test_sam]$ ls

hello.asm hello.o

[hadoop@sam1 test_sam]$ ld -s -o hello hello.o

[hadoop@sam1 test_sam]$ ls

hello hello.asm hello.o

[hadoop@sam1 test_sam]$ ./hello

Hello, world!

[hadoop@sam1 test_sam]$

命令说明:

nasm -f elf hello.asm-->汇编

****************************************************************************************************************************************************************

-f [format] Specifies the output file format. To see a list of valid output formats, use the -hf option.

nasm -hf可以查看到:

valid output formats for -f are (`*' denotes default):

* bin flat-form binary files (e.g. DOS .COM, .SYS)

ith Intel hex

srec Motorola S-records

aout Linux a.out object files

aoutb NetBSD/FreeBSD a.out object files

coff COFF (i386) object files (e.g. DJGPP for DOS)

elf32 ELF32 (i386) object files (e.g. Linux)

elf64 ELF64 (x86_64) object files (e.g. Linux)

as86 Linux as86 (bin86 version 0.3) object files

obj MS-DOS 16-bit/32-bit OMF object files

win32 Microsoft Win32 (i386) object files

win64 Microsoft Win64 (x86-64) object files

rdf Relocatable Dynamic Object File Format v2.0

ieee IEEE-695 (LADsoft variant) object file format

macho32 NeXTstep/OpenStep/Rhapsody/Darwin/MacOS X (i386) object files

macho64 NeXTstep/OpenStep/Rhapsody/Darwin/MacOS X (x86_64) object files

dbg Trace of all info passed to output stage

elf ELF (short name for ELF32)

macho MACHO (short name for MACHO32)

win WIN (short name for WIN32)

****************************************************************************************************************************************************************

ld -s -o hello hello.o-->链接;貌似不写-s这个选项也能成功!

****************************************************************************************************************************************************************

ld命令

ld combines a number of object and archive files, relocates their data and ties up symbol references. Usually the last step in compiling a program is to run ld.

参数

-o Use output as the name for the program produced by ld; if this option is not specified, the name a.out is used by default.

-s Omit all symbol information from the output file.

****************************************************************************************************************************************************************

参考资料:

NASM x86汇编入门指南
http://blog.csdn.net/flickedball/archive/2009/11/15/4812051.aspx
NASM helloworld实例
http://hi.baidu.com/wolfand11/blog/item/08a153ee0df56d202cf5348e.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: