section .data
message: db 'Hello World!' ;声明一个字节类型(byte)的字符数组
msglength: equ 12 ;声明字节数组的长度
buffersiz: dw 1024 ;声明一个1024大小(字)的缓存
section .bss
filename: resb 255 ;定义255个字节的内存空间
number: resb 1
bignum: resw 1 ;定义1个字的内存空间(1字=2字节)
realarray: resq 10 ;定义10个reals大小的数组
section .text
global _start
_start:
pop ebx ;这里是程序开始执行的入口
.
.
.
mov eax,1 ;exit系统调用
mov ebx,0 ;返回参数是0
int 80h ;使用80h中断,然后系统内核便开始调用函数
section .data
hello: db 'Hello World!' ;字符
helloLen equ $-hello ;字符的长度
section .text
global _start
_start:
mov eax,4 ;sys_write的系统调用
mov ebx,1 ;参数1,文件描述符,stdout是1
mov ecx,hello ;字符的起始地址
mov edx,helloLen ;字符的长度
int 80h ;系统调用
mov eax,1 ;sys_exit的系统调用
mov ebx,0 ;sys_exit的返回参数0,表示无错误
int 80h
./program foo bar 42
则现在程序的栈是如下形式: 现在,我们可以写一个获取其三个参数的程序出来: section .text
global _start
_start:
pop eax ;获取参数个数:3
pop ebx ;获取程序名称:program
pop ebx ;获取第一个参数:foo
pop ecx ;获取第二个参数:bar
pop edx ;获取第三个参数:42
mov eax,1
mov ebx,0
int 80h ;退出
3.2 “过程”和跳转 NASM中没有TASM中的过程定义,但是可以使用标号来代替。例如: 其中有一点需要注意: 你可以 jump 到一个标号,但是你必须 call 一个 过程。 假设现在有如下代码: if(AX == 'w') {
writeFile();
} else {
doSomethingElse();
}
那么其对应的汇编将是如下形式: cmp AX,'w' ;
jne skipWrite ;
call writeFile ;
jmp outOfThisMess ;
skipWrite:
call doSomethingElse
outOfThisMess:
;
3.3 Linux和DOS汇编程序对比 3.3.1 “Hello World”程序输出对比 对比说明: (1)DOS下的前三行,在Linux中是不需要的,因为Linux是一个32位的保护模式的操作系统,因此所有的寄存器和分页都已经是32位的,无需特殊处理,因此就不需要段寄存器,并且也不需要设置栈的大小。 (2)Linux下的NASM和DOS下的TASM/MASM的语法区别: 1) NASM使用SECTION .DATA而不是MASM中的.DATA。 2) NASM运行我们直接使用EQU定义常量,例如:bufferlen :equ 400,那么在程序中bufferlen就等于400,这意味着我们不必使用括号来去该地址的内容。 3) NASM使用$表示当前行偏移SECTION的地址,如:hello: db 'Hello world!',10 helloLen: equ $-hello 中的$就表示当前行的偏移地址,$-hello表示当前行和上一行相差的距离,即字符的长度。 4) Linux下可以直接使用字符长度打印出字符,不必像DOS那样采用$-terminated的形式。 5) 为了打印出字符后换行,在Linux中需要加一个linefeed character(10),但是在DOS下,必须使用一个linefeed character(10)和一个carriage return(13)。 6) Linux下的代码段叫.TEXT,而DOS下的叫.CODE 7) Linux下的代码段,必须以GLOBAL XXX开始,这样做的目的是告诉系统内核程序开始执行的地址。 8) 由于Linux下无需考虑段寄存器,所以Linux下的汇编代码没有ASSUME关键字。 9) Linux下代码段(.text section)的结束不需要想DOS那样 END XXX。 (3) DOS下汇编程序中,START标签的前两句主要表示:DS寄存器指向 data segment;CS寄存器指向code segment。Linux直接使用32位寄存器,所以不需要这么设置。 (4) 在16位的DOS汇编程序中,我们使用16位的寄存器 AX、BX、CX、DX等。但是在32位的Linux中,我们使用扩展寄存器 EAX、EBX、ECX、EDX等。其中 AX 是 EAX 的低16位,AH 是 AX的高8位,AL 是 AX 的底8位,没有EAL这种寄存器。 (5) 在DOS中,如果我们想将变量的地址放进寄存器中,我们必须使用offset关键字来将其放进正确的段寄存器中。但是在Linux中不需要如此。 (6) 在DOS中,我们使用 int 21h 中断来调用 DOS 服务来打印字符。但是在Linux中,我们使用 int 80h 中断来调用 系统调用 来打印字符。并且其参数放置位置不同(参见3.1)。 (7) 退出调用的不同之处和(6)类似。 3.3.2 命令参数及文件写入对比 原文始发于微信公众号(汇编语言):如何在Linux下写汇编
免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论