2010-10-23 32 views
3

J'ai trouvé un fichier pdf appelé: ProgrammingGroundUp-1-0-booksize.pdf, et l'un des projets est de faire un programme d'assemblage qui prend dans les fichiers et les convertit en majuscules, `Comment faites-vous un programme d'assemblage x86 dans Linux qui convertit les fichiers en majuscules?

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

l'assembleur est appelé "comme", et le code est sur la page 87 du fichier, vous pouvez facilement obtenir si vous le rechercher sur google, aussi le code ne pas copier et coller correctement pour une raison quelconque, de sorte que vous pourriez parfois voir des choses comme : jmp to_another_point

J'ai essayé de m'en débarrasser autant que possible, mais il y en a peut-être encore, et certains des commentaires étaient probablement st dans le processus, donc je suggère d'ouvrir le fichier pdf d'origine. Je cours sous Linux Ubuntu version 10.04.1, j'utilise comme version 2.20.1, et le problème est qu'il crée le fichier, mais le fichier est toujours vide.

+0

me excuse, qu'est-ce que vous voulez exactement ici? –

+0

Quelle est la ligne de commande que vous utilisez pour appeler? – user434507

+0

FYI, un ET/OR simple de 32 est une façon plus simple de faire des conversions ASCII majuscules/minuscules ... –

Répondre

0

Je pense que vous pouvez soustraire 32 de la valeur des lettres pour l'obtenir en majuscules, car ils ont une différence de valeur de 32. Comme ceci:

  make_cap:      # function fore making capital letters 

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

jmp  other_function 

pop 
ret