linux汇编读取文件操作系统,【Linux x86汇编踩坑】文件读写(一)读取文件并输出...

【Linux x86汇编踩坑】文件读写

前言

linux的文件是unix的文件处理方式,因此,无论linux文件是什么程序创建的,都可以作为连续的字节流进行访问,明确这一点是相当重要的。

文件调用号

首先看看几个关于文件的系统调用号

3 //读

4 //写

5 //打开

6 //关闭

如果想知道更多linux系统调用号请移步Linux系统调用号。

对文件的操作都需要系统来完成,因此当我们需要打开或者读写一个文件时,需要向系统发出中断信号,由系统来完成这些操作,因为操作系统的安全性,这些对文件的操作都是放在管态中执行的,向系统发送中断信号都是通知cpu从目态进入管态。所以在文件读写中,向系统发送中断信号是必不可少的。

打开文件

当我们需要打开一个文件时,我们要告诉linux打开的文件名,并以特定的方式打开(read,write,create等),这是通过open系统调用处理的,通常来说,需要对文件操作都要经过打开这一步骤,但是有三个文件例外,这三个文件不是说不需要打开,而是系统在程序运行的过程中就已经帮我们完成了,它们是stdin,stdout,stderr分别对应标准输入文件,标准输出文件,标准错误文件,stdin通常指代键盘,用来接收键盘的输入,stdout通常指带屏幕,用来输出东西在屏幕上,stderr,当有错误发生的时,可以往里面写入错误信息。

在打开文件之前,我们需要将系统调用号放入%eax,文件的首地址放在%ebx中,以数字表示的读写意图放在%ecx中(通常用0来表示读,03101表示写),权限集合作为数字放在%edx中(默认为0666)。

把指定的信息放入相应的寄存器之后,就可以向系统发送中断信号来通知打开文件了。

打开文件过后,文件描述符通常放在%eax中,文件描述符可以代表一个文件,在整个程序中你都可以通过文件描述符对文件进行操作,在文件使用完毕后,你可以通知linux将文件关闭,这时,你的文件描述符不会有效。

以下是一个简单的打开文件示例,我们以打开当前目录下的data文件为例

openFile.s

.section .data

.section .text

.globl _start

_start:

mov %esp, %ebp

#系统调用号

movl $5, %eax

#文件名

movl 8(%ebp), %ebx

#读写意图为只读

movl $0, %ecx

#系统权限

movl $0666, %edx

#系统中断

int $0x80

movl %eax, %ebx

movl $1, %eax

int $0x80

汇编连接运行

as openFile.s -o openFile.o

ld openFile.o -o openFile

./openFile data

读取文件

打开文件之后,我们可以对文件进行读的操作,为了进行该调用,你必须将文件描述符放入%ebx,将储存数据的缓冲地址放入%ecx,将缓冲区的大小放入%edx,读操作返回读取的字符数或者一个错误代码,错误代码通常是负数。

写入文件

写入文件和读取文件参数基本一致,唯一的区别是缓冲区里应该已经填满了要写的数据。

读取文件并输出示例

下面我上一个示例,在data文件中,我写上一些信息,然后写一个汇编程序,将该文件里的内容输出到屏幕上:

为了方便我会用.equ定义一系列的别名

test.s

.section .data

#系统调用号

.equ SYS_EXIT, 1

.equ SYS_READ, 3

.equ SYS_WRITE, 4

.equ SYS_OPEN, 5

.equ SYS_CLOSE, 6

#文件打开选项

.equ FILE_READONLY, 0

.equ FILE_WRITE, 03101

#系统调用中断

.equ SYS_INTERRUP, 0x80

#标准文件描述符

.equ STD_IN, 0

.equ STD_OUT, 1

.equ STD_ERR, 2

.section .bss

#申请缓冲区20byte

.equ BUFFER_SIZE, 20

.lcomm BUFFER_DATA, BUFFER_SIZE

.section .text

.globl _start

_start:

#文件名入栈

movl %esp, %ebp

pushl 8(%ebp)

# 打开文件

call openFile

addl $4, %esp

# 文件描述符保存在%eax

pushl %eax

# 读取文件

call readFile

addl $4, %esp

call writeFile

movl %eax, %ebx

movl $SYS_EXIT, %eax

int $SYS_INTERRUP

#系统调用打开文件

.type openFile, @function

openFile:

pushl %ebp

movl %esp, %ebp

#系统调用号

movl $SYS_OPEN, %eax

#文件名

movl 8(%ebp), %ebx

#读写意图

movl $FILE_READONLY, %ecx

#系统权限

movl $0666, %edx

#系统中断

int $SYS_INTERRUP

popl %ebp

ret

#读取文件

.type readFile, @function

readFile:

pushl %ebp

movl %esp, %ebp

#文件描述符

movl 8(%ebp), %ebx

#系统调用号

movl $SYS_READ, %eax

#缓冲区

movl $BUFFER_DATA, %ecx

#缓冲区大小

movl $BUFFER_SIZE, %edx

#系统调用

int $SYS_INTERRUP

popl %ebp

ret

#写入文件

.type writeFile, @function

writeFile:

pushl %ebp

movl %esp, %ebp

#文件描述符

movl $1, %ebx

#系统调用号

movl $SYS_WRITE, %eax

#缓冲区

movl $BUFFER_DATA, %ecx

#缓冲区大小

movl $BUFFER_SIZE, %edx

#系统调用

int $SYS_INTERRUP

popl %ebp

ret

我们在data里写上

hello assembly

汇编连接

$as test.s -o test.o

$ld test.o -o test

$./test data

hello assembly

大功告成!这里为了划分功能模块,把他们都写成了函数。值得注意的是,在进行传入文件名操作的时候,文件名为当前esp的往上8个地址

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值