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

  • 相关阅读:
    Leetcode 121. Best Time to Buy and Sell Stock
    Leetcode 120. Triangle
    Leetcode 26. Remove Duplicates from Sorted Array
    Leetcode 767. Reorganize String
    Leetcode 6. ZigZag Conversion
    KMP HDU 1686 Oulipo
    多重背包 HDU 2844 Coins
    Line belt 三分嵌套
    三分板子 zoj 3203
    二分板子 poj 3122 pie
  • 原文地址:https://www.cnblogs.com/openix/p/2444435.html
Copyright © 2011-2022 走看看