shrimpah
shrimpah

Reputation: 125

assembly find min max values

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

Answers (1)

shrimpah
shrimpah

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

Related Questions