Reputation: 125
My problem here is that using an input file where the first integer defines how many integers are in the file, (minus that one) and then sums all the integers, followed by finding the highest and lowest integers and printing them out.
My error is that the highest integer is not being found. I instantiated the high variable in the beginning with 0 so that it should be updated during the first pass, and it's never being updated, yet my lowest value is found and printed without problem, therefore I assumed my problem lay hidden in my jumps, but nothing I seem to change, or comment out changes my output. It must be a simple error, but I'm not very familiar with assembly and it's giving me a lot of problems.
;; NASM program to read from cmd line arg, open file, read first line, and print first line to screen
;; Uses fopen, fscanf, and printf
;; For help using the stack to write subroutines, consult the assembly lecture "Stack Basics and Procedure Calls"
;; nasm -f elf cfunctions.asm
;; gcc -o output cfunctions.o -m32
;; output input.txt
%include "mine.inc"
extern printf
extern fopen
extern sscanf
extern fscanf
%define STDIN 0
%define STDOUT 1
%define SYSCALL_EXIT 1
%define SYSCALL_READ 3
%define SYSCALL_WRITE 4
global main
section .data
read_char: db 'r', 0
format: db "%d",10,0
filename: dd 0
file_pointer: dd 0
number: dd 0
string: db "The integer is %d",10,0
sumString: db "The sum is %d",10,0
lowString: db "The lowest number is %d",10,0
highString: db "The highest number is %d",10,0
section .bss
temp resb 8; reserves a lot for the manipulated item
low: resb 2 ; reserves 2 bytes buffer for low, because if theres a low under 65k i'll be so mad!!
high: resb 8; reserves a lot for a big number
sum: resb 8 ; reserves a lot for the sum
size: resb 2; only need a word for ints 1000 (hopefully)
section .text
main:
; instatiate the min and max values
mov eax, 65535
mov [low], eax ; starts the low really high
xor eax,eax; sets eax to zero
mov [high], eax ; high is now zero
;; Get the filename, pointer to input filename is returned, will equal 0 for an invalid filname
push dword filename ; Push address of the pointer to the filename
call GetCommandLine ; Return address pushed to stack, Go to line 72, GetCommandLine
add esp, 4 ; Resets stack value (equivalent to 'pop' inst)
;; (You need to insert code here to error check filename)
;; Open the file using fopen
;; Equivalent to eax = fopen("input.txt", "r") if programmed in C
push dword read_char ; "r" to open a file for reading
push dword [filename] ; filename from cmd line arg
call fopen
add esp, 8
;; Error check fstream returned from fopen
cmp eax, 0
je Exit
mov [file_pointer], eax
;; Read a value from the file using fscanf
push dword number ; Address of 'number'
push dword format ; %d to read an integer
push dword [file_pointer] ; fstream from fopen
call fscanf
add esp, 12
mov ecx, [number] ;
mov [size], ecx ;
xor ecx, ecx
loopFile:
;; Read a value from the file using fscanf
push dword number ; Address of 'number'
push dword format ; %d to read an integer
push dword [file_pointer] ; fstream from fopen
call fscanf
add esp, 12
;; sum is calculated here
mov eax, [number]
mov [temp], eax ; temp is now the current number from the file
add [sum], eax ;
;; lowest is calculated here
mov ebx, eax;[temp]
mov ecx, [low]
cmp ebx,ecx ; compares if temp is less than lowest
jl lessThan
jmp highest ; test2 maybe it's not jumping
highest: ;; higest is calculated here
mov ebx, eax; [temp]
mov ecx, [high]
cmp ebx,ecx
jg higherThan
jmp count ; test2
;; Print every int in the file
count:
push dword [number]
push dword string
call printf
add esp, 8
;count:
;counter of how many ints left
mov ecx, [size]; moves into ecx
dec ecx ; decreminte ecx
mov [size], ecx ;
cmp ecx, 0;
jg loopFile ; jumps to the beginining of the loop
;; prints the sum
push dword [sum]
push dword sumString
call printf
add esp,8
;; prints the lowest
push dword [low]
push dword lowString
call printf
add esp,8
;;prints the highest
push dword [high]
push dword highString
call printf
add esp,8
Exit:
mov EAX, SYSCALL_EXIT
mov EBX, 0
int 080h
ret
lessThan:
mov ebx, [temp]
;mov ecx, [low]
;mov ecx, ebx
mov [low], ebx ; moves lowest into low
jmp highest ; jumps to next comparison
higherThan:
mov ebx, [temp]
;mov ecx, [high]
;mov ecx,ebx
mov [high], ebx ; moves highest into high
jmp count
GetCommandLine:
;; Macros to move esp into ebp and push regs to be saved
Enter 0
Push_Regs ebx, ecx, edx
;; Initially sets [filename] to 0, remains 0 if there's an error
mov ebx, [ebp + 8]
mov [ebx], dword 0
;; Get argc (# of arguments)
mov ecx, [ebp + 16]
;; Checks the value of argc, should be 2 (a.out and input.txt), includes the if statement macro
cmp ecx, 2
if ne
jmp gcl_done
endif
;; Get argv[0] ("a.out"/"cfunctions" or the executable, this is not used in the project)
;; Consult slide 6 of Stack Basics... lecture
mov ecx, [ebp + 20] ; ptr to args ptr
mov ebx, [ecx] ; argv[0]
;; Get argv[1] ("input.txt")
mov ecx, [ebp + 20] ; ptr to args ptr
mov ebx, [ecx + 4] ; argv[1]
;; Set the filename pointer arg on the stack to the address of the filename
mov edx, [ebp + 8]
mov [edx], ebx
gcl_done:
;; Macros to return
Pop_Regs ebx, ecx, edx
Leave
;; Return
ret
Upvotes: 1
Views: 2745
Reputation: 125
As Frank Kotler mentioned, the problem was that my low variable needed to be declared as a full 8 bytes. I believe when accessing memory, values were overlapping and changing my low value when storing new values in that accessed memory, but changing my low to 8 bytes fixed my problem.
Upvotes: 1