1

ここでの私の問題は、最初の整数がファイル内の整数の数を定義する入力ファイルを使用し(その1を差し引いたもの)、次にすべての整数を合計し、続いて最大および最小の整数を見つけて出力することです。

私のエラーは、最大の整数が見つからないことです。最初のパス中に更新されるように、最初に高変数を 0 でインスタンス化し、更新されることはありませんが、最小値が見つかって問題なく出力されるため、問題はジャンプに隠されていると想定しましたが、何も変更していないように見えるか、コメントアウトすると出力が変更されます。単純なエラーに違いありませんが、私はアセンブリにあまり慣れていないため、多くの問題が発生しています。

;; 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
4

1 に答える 1

1

Frank Kotler が述べたように、問題は、low 変数を完全な 8 バイトとして宣言する必要があることでした。メモリにアクセスすると、値が重複し、アクセスしたメモリに新しい値を格納するときに低い値が変更されていたと思いますが、低い値を 8 バイトに変更すると問題が解決しました。

于 2013-10-24T01:56:44.540 に答える