四、Linux汇编——文件中结构化数据的操做(上)

一、概述

    本篇主要针对以下结构型记录,编写程序进行处理。主要有:读数据操做、修改数据、写数据操做。每一个程序将分开书写。同时,本篇程序使用新技术,将几段代码分别存放在不一样文件中。linux

    本程序包含三个部分:(1)将三个记录写入文件中函数

                                        (2)显示文件中的记录编码

                                        (3)将每一个记录中的年龄
spa

二、记录结构:

采用外文名字进行存储:名——40字节;姓——40字节;地址——240字节;年龄——4字节code

由以上结构,定义以下常量,并存于文件record-def.s文件中:ci

.equ RECORD_FIRSTNAME, 0
.equ RECORD_LASTNAME, 40
.equ RECORD_ADDRESS, 80
.equ RECORD_AGE, 320
.equ RECORD_SIZE, 324

如下为读取文件操做中经常使用的常数,存储在文件linux.s中:it

#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

三、读、写函数

一、读函数

下面函数放在read-record.s文件中
io

.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

二、写函数

下面函数放在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

四、将三条硬编码记录写入文件:

具体步骤为:打开文件,写3条记录,关闭文件。输入如下代码到write-records.s文件中function

.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

程序说明:

一、.include "linux.s"表示应用文件,和C语言中的#include宏声明相同。

二、.rept和.endr为重复填充某个数据,须要指明填充次数、填充的数据类型、填充的值

三、编译、连接,执行:

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

相关文章
相关标签/搜索