zoukankan      html  css  js  c++  java
  • gas 多文件组织

    gas多文件工程

    摘自:Programming from Groundup   Chapter 6

    主要目的是了解如何组织多文件工程(形式)

    文件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:

    #Common Linux Definitions

    #System Call Numbers

    .equ SYS_EXIT, 1

    .equ SYS_READ, 3

    .equ SYS_WRITE, 4

    .equ SYS_OPEN, 5

    .equ SYS_CLOSE, 6

    .equ SYS_BRK, 45

    #System Call Interrupt Number

    .equ LINUX_SYSCALL, 0x80

    #Standard File Descriptors

    .equ STDIN, 0

    .equ STDOUT, 1

    .equ STDERR, 2

    #Common Status Codes

    .equ END_OF_FILE, 0

    第一个程序Writing Records

    文件:write-record.s

    .include "linux.s"

    .include "record-def.s"

    #PURPOSE: This function writes a record to

    # the given file descriptor

    #

    #INPUT: The file descriptor and a buffer

    #

    #OUTPUT: This function produces a status code

    #

    #STACK LOCAL VARIABLES

    .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

    #NOTE - %eax has the return value, which we will

    # give back to our calling program

    popl %ebx

    movl %ebp, %esp

    popl %ebp

    ret

    文件write-records.s

    .include "linux.s"

    .include "record-def.s"

    .section .data

    #Constant data of the records we want to write

    #Each text data item is padded to the proper

    #length with null (i.e. 0) bytes.

    #.rept is used to pad each item. .rept tells

    #the assembler to repeat the section between

    #.rept and .endr the number of times specified.

    #This is used in this program to add extra null

    #characters at the end of each field to fill

    #it up

    record1:

    .ascii "Fredrick\0"

    .rept 31 #Padding to 40 bytes

    .byte 0

    .endr

    .ascii "Bartlett\0"

    .rept 31 #Padding to 40 bytes

    .byte 0

    .endr

    .ascii "4242 S Prairie\nTulsa, OK 55555\0"

    .rept 209 #Padding to 240 bytes

    .byte 0

    .endr

    .long 45

    record2:

    .ascii "Marilyn\0"

    .rept 32 #Padding to 40 bytes

    .byte 0

    .endr

    .ascii "Taylor\0"

    .rept 33 #Padding to 40 bytes

    .byte 0

    .endr

    .ascii "2224 S Johannan St\nChicago, IL 12345\0"

    .rept 203 #Padding to 240 bytes

    .byte 0

    .endr

    .long 29

    record3:

    .ascii "Derrick\0"

    .rept 32 #Padding to 40 bytes

    .byte 0

    .endr

    .ascii "McIntire\0"

    .rept 31 #Padding to 40 bytes

    .byte 0

    .endr

    .ascii "500 W Oakland\nSan Diego, CA 54321\0"

    .rept 206 #Padding to 240 bytes

    .byte 0

    .endr

    .long 36

    #This is the name of the file we will write to

    file_name:

    .ascii "test.dat\0"

    .equ ST_FILE_DESCRIPTOR, -4

    .globl _start

    _start:

    #Copy the stack pointer to %ebp

    movl %esp, %ebp

    #Allocate space to hold the file descriptor

    subl $4, %esp

    #Open the file

    movl $SYS_OPEN, %eax

    movl $file_name, %ebx

    movl $0101, %ecx #This says to create if it

    #doesn’t exist, and open for

    #writing

    movl $0666, %edx

    int $LINUX_SYSCALL

    #Store the file descriptor away

    movl %eax, ST_FILE_DESCRIPTOR(%ebp)

    #Write the first record

    pushl ST_FILE_DESCRIPTOR(%ebp)

    pushl $record1

    call write_record

    addl $8, %esp

    #Write the second record

    pushl ST_FILE_DESCRIPTOR(%ebp)

    pushl $record2

    call write_record

    addl $8, %esp

    #Write the third record

    pushl ST_FILE_DESCRIPTOR(%ebp)

    pushl $record3

    call write_record

    addl $8, %esp

    #Close the file descriptor

    movl $SYS_CLOSE, %eax

    movl ST_FILE_DESCRIPTOR(%ebp), %ebx

    int $LINUX_SYSCALL

    #Exit the program

    movl $SYS_EXIT, %eax

    movl $0, %ebx

    int $LINUX_SYSCALL

    To build the application, run the commands:

    as write-records.s -o write-record.o

    as write-record.s -o write-record.o

    ld write-record.o write-records.o -o write-records

    第二个程序Reading Records

    文件read-record.s

    .include "record-def.s"

    .include "linux.s"

    #PURPOSE: This function reads a record from the file

    # descriptor

    #

    #INPUT: The file descriptor and a buffer

    #

    #OUTPUT: This function writes the data to the buffer

    # and returns a status code.

    #

    #STACK LOCAL VARIABLES

    .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

    int $LINUX_SYSCALL

    #NOTE - %eax has the return value, which we will

    # give back to our calling program

    popl %ebx

    movl %ebp, %esp

    popl %ebp

    ret

    文件count-chars.s

    #PURPOSE: Count the characters until a null byte is reached.

    #

    #INPUT: The address of the character string

    #

    #OUTPUT: Returns the count in %eax

    #

    #PROCESS:

    # Registers used:

    # %ecx - character count

    # %al - current character

    # %edx - current character address

    .type count_chars, @function

    .globl count_chars

    #This is where our one parameter is on the stack

    .equ ST_STRING_START_ADDRESS, 8

    count_chars:

    pushl %ebp

    movl %esp, %ebp

    #Counter starts at zero

    movl $0, %ecx

    #Starting address of data

    movl ST_STRING_START_ADDRESS(%ebp), %edx

    count_loop_begin:

    #Grab the current character

    movb (%edx), %al

    #Is it null?

    cmpb $0, %al

    #If yes, we’re done

    je count_loop_end

    #Otherwise, increment the counter and the pointer

    incl %ecx

    incl %edx

    #Go back to the beginning of the loop

    jmp count_loop_begin

    count_loop_end:

    #We’re done. Move the count into %eax

    #and return.

    movl %ecx, %eax

    popl %ebp

    ret

    文件write-newline.s

    .include "linux.s"

    .globl write_newline

    .type write_newline, @function

    .section .data

    newline:

    .ascii "\n"

    .section .text

    .equ ST_FILEDES, 8

    write_newline:

    pushl %ebp

    movl %esp, %ebp

    movl $SYS_WRITE, %eax

    movl ST_FILEDES(%ebp), %ebx

    movl $newline, %ecx

    movl $1, %edx

    int $LINUX_SYSCALL

    movl %ebp, %esp

    popl %ebp

    ret

    文件read-records.s

    .include "linux.s"

    .include "record-def.s"

    .section .data

    file_name:

    .ascii "test.dat\0"

    .section .bss

    .lcomm record_buffer, RECORD_SIZE

    .section .text

    #Main program

    .globl _start

    _start:

    #These are the locations on the stack where

    #we will store the input and output descriptors

    #(FYI - we could have used memory addresses in

    #a .data section instead)

    .equ ST_INPUT_DESCRIPTOR, -4

    .equ ST_OUTPUT_DESCRIPTOR, -8

    #Copy the stack pointer to %ebp

    movl %esp, %ebp

    #Allocate space to hold the file descriptors

    subl $8, %esp

    #Open the file

    movl $SYS_OPEN, %eax

    movl $file_name, %ebx

    movl $0, %ecx #This says to open read-only

    movl $0666, %edx

    int $LINUX_SYSCALL

    #Save file descriptor

    movl %eax, ST_INPUT_DESCRIPTOR(%ebp)

    #Even though it’s a constant, we are

    #saving the output file descriptor in

    #a local variable so that if we later

    #decide that it isn’t always going to

    #be STDOUT, we can change it easily.

    movl $STDOUT, ST_OUTPUT_DESCRIPTOR(%ebp)

    record_read_loop:

    pushl ST_INPUT_DESCRIPTOR(%ebp)

    pushl $record_buffer

    call read_record

    addl $8, %esp

    #Returns the number of bytes read.

    #If it isn’t the same number we

    #requested, then it’s either an

    #end-of-file, or an error, so we’re

    #quitting

    cmpl $RECORD_SIZE, %eax

    jne finished_reading

    #Otherwise, print out the first name

    #but first, we must know it’s size

    pushl $RECORD_FIRSTNAME + record_buffer

    call count_chars

    addl $4, %esp

    movl %eax, %edx

    movl ST_OUTPUT_DESCRIPTOR(%ebp), %ebx

    movl $SYS_WRITE, %eax

    movl $RECORD_FIRSTNAME + record_buffer, %ecx

    int $LINUX_SYSCALL

    pushl ST_OUTPUT_DESCRIPTOR(%ebp)

    call write_newline

    addl $4, %esp

    jmp record_read_loop

    finished_reading:

    movl $SYS_EXIT, %eax

    movl $0, %ebx

    int $LINUX_SYSCALL

    To build this program, we need to assemble all of the parts and link them together:

    as read-record.s -o read-record.o

    as count-chars.s -o count-chars.o

    as write-newline.s -o write-newline.o

    as read-records.s -o read-records.o

    ld read-record.o count-chars.o write-newline.o \

    read-records.o -o read-records

    第三个程序Modifying the Records

    文件add-year.s

    .include "linux.s"

    .include "record-def.s"

    .section .data

    input_file_name:

    .ascii "test.dat\0"

    output_file_name:

    .ascii "testout.dat\0"

    .section .bss

    .lcomm record_buffer, RECORD_SIZE

    #Stack offsets of local variables

    .equ ST_INPUT_DESCRIPTOR, -4

    .equ ST_OUTPUT_DESCRIPTOR, -8

    .section .text

    .globl _start

    _start:

    #Copy stack pointer and make room for local variables

    movl %esp, %ebp

    subl $8, %esp

    #Open file for reading

    movl $SYS_OPEN, %eax

    movl $input_file_name, %ebx

    movl $0, %ecx

    movl $0666, %edx

    int $LINUX_SYSCALL

    movl %eax, ST_INPUT_DESCRIPTOR(%ebp)

    #Open file for writing

    movl $SYS_OPEN, %eax

    movl $output_file_name, %ebx

    movl $0101, %ecx

    movl $0666, %edx

    int $LINUX_SYSCALL

    movl %eax, ST_OUTPUT_DESCRIPTOR(%ebp)

    loop_begin:

    pushl ST_INPUT_DESCRIPTOR(%ebp)

    pushl $record_buffer

    call read_record

    addl $8, %esp

    #Returns the number of bytes read.

    #If it isn’t the same number we

    #requested, then it’s either an

    #end-of-file, or an error, so we’re

    #quitting

    cmpl $RECORD_SIZE, %eax

    jne loop_end

    #Increment the age

    incl record_buffer + RECORD_AGE

    #Write the record out

    pushl ST_OUTPUT_DESCRIPTOR(%ebp)

    pushl $record_buffer

    call write_record

    addl $8, %esp

    jmp loop_begin

    loop_end:

    movl $SYS_EXIT, %eax

    movl $0, %ebx

    int $LINUX_SYSCALL

     

     

    To build it, type the following4:

    as add-year.s -o add-year.o

    ld add-year.o read-record.o write-record.o -o add-year

  • 相关阅读:
    Angular入门到精通系列教程(12)- 路由(Routing)
    Angular入门到精通系列教程(11)- 模块(NgModule),延迟加载模块
    error: file '/boot/grub/i386-pc/normal.mod' not found解决方案
    mysql常用查询
    mysql数据库表中随机生成时间
    成本分析报表
    弹窗维护字段POPUP_GET_VALUES
    返回上一个屏幕
    PM停机时间问题处理
    IP41
  • 原文地址:https://www.cnblogs.com/openix/p/2444435.html
Copyright © 2011-2022 走看看