1、概述
本篇主要针对如下结构型记录,编写程序进行处理。主要有:读数据操作、修改数据、写数据操作。每个程序将分开书写。同时,本篇程序使用新技术,将几段代码分别存放在不同文件中。
本程序包含三个部分:(1)将三个记录写入文件中
(2)显示文件中的记录
(3)将每个记录中的年龄
2、记录结构:
采用外文名字进行存储:名——40字节;姓——40字节;地址——240字节;年龄——4字节
由以上结构,定义如下常量,并存于文件record-def.s文件中:
.equ RECORD_FIRSTNAME, 0
.equ RECORD_LASTNAME, 40
.equ RECORD_ADDRESS, 80
.equ RECORD_AGE, 320
.equ RECORD_SIZE, 324
以下为读取文件操作中常用的常数,存储在文件linux.s中:
#linux常量定义
#系统调用号
.equ SYS_EXIT, 1
.equ SYS_READ, 3
.equ SYS_WRITE, 4
.equ SYS_OPEN, 5
.equ SYS_CLOSE, 6
.equ SYS_BRK, 45
#系统调用中断号
.equ LINUX_SYSCALL, 0x80
#标准文件描述符
.equ STDIN, 0
.equ STDOUT,1
.equ STDERR, 2
#通用状态码
.equ END_OF_FILE, 0
3、读、写函数
1、读函数
下面函数放在read-record.s文件中
.include "record-def.s"
.include "linux.s"
#目的:该函数根据文件描述符读取一条记录
#输入:文件描述符、缓冲区
#栈局部变量
.equ ST_READ_BUFFER, 8
.equ ST_FILEDES, 12
.section .text
.globl read_record
.type read_record, @function
read_record: pushl %ebp
movl %esp, %ebp
pushl %ebx #如下图为当前栈中的内容
movl ST_FILEDES(%ebp), %ebx
movl ST_READ_BUFFER(%ebp), %ecx
movl $RECORD_SIZE, %edx
movl $SYS_READ, %eax #由于系统调用将返回值传给%eax,所以需将该值传回给调用程序
int $LINUX_SYSCALL
popl %ebx
movl %ebp, %esp
popl %ebp
ret
2、写函数
下面函数放在write-record.s文件中
.include "record-def.s"
.include "linux.s"
#目的:将一条记录写入文件中
#输入:文件描述符和缓冲
#输出:状态码
#栈局部变量
.equ ST_WRITE_BUFFER, 8
.equ ST_FILEDES, 12
.section .text
.globl write_record
.type write_record, @function
write_record: pushl %ebp
movl %esp, %ebp
pushl %ebx
movl $SYS_WRITE, %eax
movl $ST_FILEDES(%ebp), %ebx
movl $ST_WRITE_BUFFER(%ebp),%ecx
movl $RECORD_SIZE, %edx
int $LINUX_SYSCALL
popl %ebp, %esp
popl %ebp
ret
4、将三条硬编码记录写入文件:
具体步骤为:打开文件,写3条记录,关闭文件。输入以下代码到write-records.s文件中
.include "record-def.s"
.include "linux.s"
.section .data
#由于每个数据长度不一致,所以使用空字节“0”填充到适当长度
#.rept是用于填充数据的伪指令,.rept和.endr之间的段重复指定次数
record1: .ascii "ming\0" #名
.rept 35 #用0填充剩下的32个字节,填充满40字节
.byte 0
.endr
.ascii "Li\0" #姓
.rept 37 #填充到40字节
.byte 0
.endr
.ascii "Beijing\0" #地址
.rept 232 #填充到240字节
.byte 0
.endr
.long 45 #年龄
record2: .ascii "Lang\0" #名
.rept 35 #用0填充剩下的32个字节,填充满40字节
.byte 0
.endr
.ascii "Qi\0" #姓
.rept 37 #填充到40字节
.byte 0
.endr
.ascii "Daliang\0" #地址
.rept 232 #填充到240字节
.byte 0
.endr
.long 23 #年龄
record3: .ascii "Yong\0" #名
.rept 35 #用0填充剩下的32个字节,填充满40字节
.byte 0
.endr
.ascii "Da\0" #姓
.rept 37 #填充到40字节
.byte 0
.endr
.ascii "Langfan\0" #地址
.rept 232 #填充到240字节
.byte 0
.endr
.long 28 #年龄
file_name: .ascii "test.dat\0" #写入的文件名
.equ ST_FILE_DESCRIPTOR, -4
.globl _start
_start: movl %esp, %ebp
subl $4, %esp #为文件描述符分配空间
#打开文件
movl $SYS_OPEN, %eax
movl $file_name, %ebx
movl $0101, %ecx #如果文件不存在则创建,打开文件用于写入数据
movl $0666, %edx
int $LINUX_SYSCALL
movl %eax, ST_FILE_DESCRIPTOR(%ebp) #存储文件描述符
#写第一条记录
pushl ST_FILE_DESCRIPTOR(%ebp) #文件描述符
pushl $record1 #记录的地址,即缓冲区的地址
call write_record
addl $8, %esp #回收空间
#写第二条记录
pushl ST_FILE_DESCRIPTOR(%ebp) #文件描述符
pushl $record2 #记录的地址
call write_record
addl $8, %esp #回收空间
#写第三条记录
pushl ST_FILE_DESCRIPTOR(%ebp) #文件描述符
pushl $record3 #记录的地址
call write_record
addl $8, %esp #回收空间
#关闭文件描述符
movl $SYS_CLOSE, %eax
movl $ST_FILE_DESCRIPTOR(%ebp), %ebx
int $LINUX_SYSCALL
#退出程序
movl $SYS_EXIT, %eax
movl $0, %ebx
int $LINUX_SYSCALL
程序说明:
1、.include "linux.s"表示应用文件,和C语言中的#include宏声明相同。
2、.rept和.endr为重复填充某个数据,需要指明填充次数、填充的数据类型、填充的值
3、编译、链接,执行:
as write-record.s -o write-record.o
as write-records.s -o write-records.o
ld write-record.o write-records.o -o write-records
执行:./write-records