四、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

相關文章
相關標籤/搜索