Gas multi-file organization

Source: Internet
Author: User

Gas multi-file Engineering

From: programming from groundup Chapter 6

The main purpose is to understand how to organize multi-file projects (Forms)

 

 

File record-def.s:

. Equ record_firstname, 0

. Equ record_lastname, 40

. Equ record_address, 80

. Equ record_age, 320

. Equ record_size, 324

 

File 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

 

First ProgramWriting records

File: write-record.s

. Include "Linux. s"

. Include "record-def.s"

# Purpose: This function writes a record

# 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

 

 

File 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 caller to repeat the section

#. 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

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

# 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

 

 

Second ProgramReading records

File 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

 

File 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

 

File 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

 

File 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 cocould 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

# 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

# End-of-file, or an error, so we're 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

 

Third ProgramModifying the records

File 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

# End-of-file, or an error, so we're 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

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.