Как вы делаете программу сборки x86 в Linux, которая преобразует файлы в верхний регистр? - PullRequest
3 голосов
/ 24 октября 2010

Я нашел файл pdf: ProgrammingGroundUp-1-0-booksize.pdf, и один из проектов - создать программу сборки, которая принимает файлы и преобразует их в верхний регистр, `

.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
.equ BUFFER_SIZE, 500
.lcomm BUFFER_DATA, BUFFER_SIZE
.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
#mode 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(%ebp)
###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(%ebp), %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(%ebp), %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
movl $SYS_CLOSE, %eax
movl ST_FD_OUT(%ebp), %ebx
int $LINUX_SYSCALL
movl ST_FD_IN(%ebp), %ebx
movl $SYS_CLOSE, %eax
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
`

ассемблер называется «как», а код находится на странице 87 файла, вы можете легко получить его, если вы посмотрите его в Google, также код по какой-то причине не копируется и не вставляется правильно, так что вы можете иногдаувидеть такие вещи, как: jmp to_another_point

Я пытался избавиться от как можно большего количества из них, но некоторые еще могли быть, и некоторые комментарии, вероятно, были потеряны в процессе, поэтому я бы предложил открытьоригинальный файл PDF.Я использую Ubuntu Linux версии 10.04.1, я использую версию 2.20.1, и проблема в том, что он создает файл, но файл всегда пуст.

Ответы [ 2 ]

6 голосов
/ 24 октября 2010

Источник для этой книги доступен , и если вы просматриваете соответствующую часть хранилища CVS , вы можете найти .s исходные файлы для различных примеров.

Этот код toupper.s - вы можете просто скачать самую последнюю версию, вместо того, чтобы возиться с копированием и вставкой.

Я только что попробовал (наСистема Debian; у меня нет ничего работающего под Ubuntu 10.04), сборка и компоновка в точности, как описано в книге, и она работала нормально.

0 голосов

Я думаю, что вы можете вычесть 32 из значения букв, чтобы получить его в верхнем регистре, так как они имеют разницу в значении 32. Например:

           make_cap:                      # function fore making capital letters

sub        $32, al                        # subtract 32 from the value of the character

jmp        other_function

pop
ret
...