(1)数据段(.data section)
数据段主要用来“声明初始化数据”,换句话说,是用来定义常“变量”的,这个“变量”主要是指在程序中不会一直变化,定义后就会保持不变。通常数据段都是用来定义常用的标号,比如:文件名、缓存大小等等,当然,你也可以使用 EQU 这个指令来实现。定义常“变量”可以使用的指令有:DB、DW、DD、DQ和DT,例如:
section .data
message: db 'Hello World!' ;声明一个字节类型(byte)的字符数组
msglength: equ 12 ;声明字节数组的长度
buffersiz: dw 1024 ;声明一个1024大小(字)的缓存
(2)变量段(.bss section)
该段主要是用来定义变量的,这里可以使用的指令有:RESB、RESW、EWSD、EWSQ和REST等,这些指令可以用来预留一些内存空间给定义的变量。例如:
section .bss
filename: resb 255 ;定义255个字节的内存空间
number: resb 1
bignum: resw 1 ;定义1个字的内存空间(1字=2字节)
realarray: resq 10 ;定义10个reals大小的数组
(3)代码段(.text section)
这部分主要是用来写汇编代码的,通常,代码段必须以 global _start(_start为标号,自定义)开头,他的主要含义是告诉内核程序是从这里开始的,内核在看到这部分变编译后的信息,就会将相关的CS:IP指向这里,然后开始执行程序。就和C函数中的main()函数类似。例如:
section .text
global _start
_start:
pop ebx ;这里是程序开始执行的入口
程序第一个例子都是hello world,有谁能告诉我为啥?
section .data
massage: db "Hello world!"
Len: equ $ - massage
section .text
global _start
_start:
mov eax,4 ; 4号调用 sys_write的系统调用
mov ebx,1 ; ebx送1表示输出,参数1,文件描述符,stdout是1
mov ecx,massage ; 字符串的首地址送入ecx
mov edx,Len ; 字符串的长度送入edx
int 80h ; 输出字串
mov eax,1 ; sys_exit的系统调用
mov ebx,0 ;sys_exit的返回参数0,表示无错误
int 80h ; 系统调用
编译:
nasm -g -f elf32 hello.asm -o hello.o
ld -g -m elf_i386 -o hello hello.o
调试:
gdb hello
(调试指令:http://www.flaotw.com/latest/2021-09-05/169.html)
代码说明:
Linux下的系统调用和DOS下的系统调用类似,主要通过以下几个步骤:
(1)将你的系统调用号放进EAX中(因为我们是在32位下,所以使用32位的EAX寄存器)。
(2)设置系统调用参数,并且依次将参数放进EBX、ECX、EDX、ESX、EDI和EBP。
(3)调用相关中断(对应Linux来说是 80h;对于DO来说是 21h)。
(4)最后的调用结果会返回到EAX中保存。
说明:第二步中的参数是按照顺序放置的,比如第一个参数放在EBX中,第二个参数放在ECX中,…第5个参数放在EDI中。但是只有Linux2.4以后的版本才至此第6个参数EBP,以上的版本只支持前5个参数。如果有多于6个参数,则EBX用来存放参数列表在内存中的位置,但是通常情况下是不会多于6个参数的。
例如:
mov eax,1 ;exit系统调用
mov ebx,0 ;返回参数是0
int 80h ;使用80h中断,然后系统内核便开始调用函数
随便看看
文章排行
本栏推荐
栏目更新
Copyright 2020 Inc. AllRights Reserved. Design by nasm第一个程序