程序集:使用.bss节中的存储空间,而不是#stack来存储文件描述符(运动问题)

时间:2019-05-01 01:56:52

标签: assembly x86 gas

我正在解决this这本书中的练习部分。

我的问题是关于本书中的toupper示例。

问题:

  

重写程序,以便它使用.bss节中的存储空间,而不是   而不是用于存储文件描述符的堆栈。

可以在website上找到默认代码。

我的代码:

#Rewrite the program so that it uses storage in the .bss section rather than the
#stack to store the file descriptors.



#PURPOSE:    This program converts an input file
#            to an output file with all letters
#            converted to uppercase.
#
#PROCESSING: 1) Open the input file
#            2) Open the output file
#            3) While we're not at the end of the input file
#               a) read part of file into our memory buffer
#               b) go through each byte of memory
#                    if the byte is a lower-case letter,
#                    convert it to uppercase
#               c) write the memory buffer to output file

.section .data

#######CONSTANTS########

#system call numbers
.equ SYS_OPEN, 5
.equ SYS_WRITE, 4
.equ SYS_READ, 3
.equ SYS_CLOSE, 6
.equ SYS_EXIT, 1

#options for open (look at
#/usr/include/asm/fcntl.h for
#various values.  You can combine them
#by adding them or ORing them)
#This is discussed at greater length
#in "Counting Like a Computer"
.equ O_RDONLY, 0
.equ O_CREAT_WRONLY_TRUNC, 03101

#standard file descriptors
.equ STDIN, 0
.equ STDOUT, 1
.equ STDERR, 2

#system call interrupt
.equ LINUX_SYSCALL, 0x80

.equ END_OF_FILE, 0  #This is the return value
                    #of read which means we've
                    #hit the end of the file

.equ NUMBER_ARGUMENTS, 2

.section .bss
#Buffer - this is where the data is loaded into
#         from the data file and written from
#         into the output file.  This should
#         never exceed 16,000 for various
#         reasons.
.equ BUFFER_SIZE, 500
.lcomm BUFFER_DATA, BUFFER_SIZE
.equ ST_FD_IN, 10
.equ ST_FD_OUT, 10

.section .text

#STACK POSITIONS
.equ ST_SIZE_RESERVE, 8
#.equ ST_FD_IN, -4
#.equ ST_FD_OUT, -8
.equ ST_ARGC, 0      #Number of arguments
.equ ST_ARGV_0, 4   #Name of program
.equ ST_ARGV_1, 8   #Input file name
.equ ST_ARGV_2, 12   #Output file name

.globl _start
_start:
###INITIALIZE PROGRAM###
#save the stack pointer
movl  %esp, %ebp

#Allocate space for our file descriptors
#on the stack
subl  $ST_SIZE_RESERVE, %esp

open_files:
open_fd_in:
###OPEN INPUT FILE###
#open syscall
movl  $SYS_OPEN, %eax
#input filename into %ebx
movl  ST_ARGV_1(%ebp), %ebx
#read-only flag
movl  $O_RDONLY, %ecx
#this doesn't really matter for reading
movl  $0666, %edx
#call Linux
int   $LINUX_SYSCALL

store_fd_in:
#save the given file descriptor
movl  %eax, ST_FD_IN(%ebp)

open_fd_out:
###OPEN OUTPUT FILE###
#open the file
movl  $SYS_OPEN, %eax
#output filename into %ebx
movl  ST_ARGV_2(%ebp), %ebx
#flags for writing to the file
movl  $O_CREAT_WRONLY_TRUNC, %ecx
#permission set for new file (if it's created)
movl  $0666, %edx
#call Linux
int   $LINUX_SYSCALL

store_fd_out:
#store the file descriptor here
movl  %eax, ST_FD_OUT

###BEGIN MAIN LOOP###
read_loop_begin:

###READ IN A BLOCK FROM THE INPUT FILE###
movl  $SYS_READ, %eax
#get the input file descriptor
movl  ST_FD_IN, %ebx
#the location to read into
movl  $BUFFER_DATA, %ecx
#the size of the buffer
movl  $BUFFER_SIZE, %edx
#Size of buffer read is returned in %eax
int   $LINUX_SYSCALL

###EXIT IF WE'VE REACHED THE END###
#check for end of file marker
cmpl $END_OF_FILE, %eax
#if found or on error, go to the end
jle   end_loop

continue_read_loop:
###CONVERT THE BLOCK TO UPPER CASE###
pushl $BUFFER_DATA     #location of buffer
pushl %eax             #size of the buffer
call  convert_to_upper
popl  %eax             #get the size back
addl  $4, %esp         #restore %esp

###WRITE THE BLOCK OUT TO THE OUTPUT FILE###
#size of the buffer
movl  %eax, %edx
movl  $SYS_WRITE, %eax
#file to use
movl  ST_FD_OUT, %ebx
#location of the buffer
movl  $BUFFER_DATA, %ecx
int   $LINUX_SYSCALL

###CONTINUE THE LOOP###
jmp   read_loop_begin

end_loop:
###CLOSE THE FILES###
#NOTE - we don't need to do error checking
#       on these, because error conditions
#       don't signify anything special here
movl  $SYS_CLOSE, %eax
movl  ST_FD_OUT, %ebx
int   $LINUX_SYSCALL

movl  $SYS_CLOSE, %eax
movl  ST_FD_IN, %ebx
int   $LINUX_SYSCALL

###EXIT###
movl  $SYS_EXIT, %eax
movl  $0, %ebx
int   $LINUX_SYSCALL

###CONSTANTS##
#The lower boundary of our search
.equ  LOWERCASE_A, 'a'
#The upper boundary of our search
.equ  LOWERCASE_Z, 'z'
#Conversion between upper and lower case
.equ  UPPER_CONVERSION, 'A' - 'a'

###STACK STUFF###
.equ  ST_BUFFER_LEN, 8 #Length of buffer
.equ  ST_BUFFER, 12    #actual buffer
convert_to_upper:
pushl %ebp
movl  %esp, %ebp

###SET UP VARIABLES###
movl  ST_BUFFER(%ebp), %eax
movl  ST_BUFFER_LEN(%ebp), %ebx
movl  $0, %edi
#if a buffer with zero length was given
#to us, just leave
cmpl  $0, %ebx
je    end_convert_loop

convert_loop:
#get the current byte
movb  (%eax,%edi, 1), %cl

#go to the next byte unless it is between
#'a' and 'z'
cmpb  $LOWERCASE_A, %cl
jl    next_byte
cmpb  $LOWERCASE_Z, %cl
jg    next_byte

#otherwise convert the byte to uppercase
addb  $UPPER_CONVERSION, %cl
#and store it back
movb  %cl, (%eax,%edi,1)
next_byte:
incl  %edi              #next byte
cmpl  %edi, %ebx        #continue unless
                       #we've reached the
                       #end
jne   convert_loop

end_convert_loop:
#no return value, just leave
movl  %ebp, %esp
popl  %ebp
ret

我尝试在.bss节中定义(.equ)文件描述符(即,将它们保留10个空格),然后在代码中使用它们。但是,尽管尝试了不同的方法,但我还是无法使它起作用。

能帮我吗?谢谢你。

1 个答案:

答案 0 :(得分:1)

.equ不保留空间。而是为标签分配一个值。要保留空间,请使用.space.lcomm指令。