2016-05-05 20 views
3

Das Ziel des folgenden Programms besteht darin, bis zu 10 vorzeichenbehaftete 8-Byte Gleitkommazahlen im Bereich -100 ≤ X ≤ 100 als Eingabe von einem Benutzer zu akzeptieren und sie in einem Array zu speichern. Die Benutzereingabe wird mit der ReadFloat Irvine-Methode empfangen. Wenn eine Zahl außerhalb dieses Bereichs eingegeben wird, soll die Subroutine die Ausführung stoppen und die Anzahl der Werte, die sich zur Zeit im Array befinden, durch eax zurücksenden. Das war nur ein kleiner Kontext, der beschreiben sollte, was das Programm tun soll. Das Problem, das ich mit diesem Code habe, besteht darin, dass es nach dem Akzeptieren des ersten Wertes nicht richtig läuft. Ich habe es so eingerichtet, dass es überprüft, ob die Eingangsnummer über -100 in L1 und dann unter oder gleich 100 in L2 ist. Wenn die Anzahl außerhalb dieses Bereichs liegt, sollte die Unterroutine nicht mehr ausgeführt werden. Wenn sie jedoch innerhalb dieses Bereichs liegt, sollte sie zu L3 & R1 fortschreiten. In L3 und R1 wird die Nummer in einem Index im SFPA-Array platziert und wenn das Array weniger als 10 Werte enthält, sollte das Programm unbedingt für weitere Iterationen zurück nach L1 springen. Der JMP-Befehl in R1 ist, wo das Problem ist. Die Subroutine in ihrem aktuellen Zustand wird die Ausführung stoppen, nachdem eine einzelne Zahl eingegeben wurde und ich kann nicht herausfinden warum. Kann jemand Hilfe leisten?x86 Assembly Beginner: Programm wird nicht korrekt durchlaufen?

INCLUDE c:\irvine\irvine32.inc 
INCLUDELIB c:\irvine\irvine32.lib 
INCLUDELIB c:\masm32\lib\user32.lib 
INCLUDELIB c:\masm32\lib\kernel32.lib 


.data 
theSFPArray REAL8 10 dup(?)    ;an array that can store up to 10 signed floating point numbers 
tempStoreFP REAL8 ?      ;this variable will temporarily store the FP number acquired from user input, and then push it onto the stack 
lengthOfSFPArray DWORD ?    ;this variable will store the length of theSFPArray. This value will be used to determine if requestSignedFloats should stop looping. 
inputLoopCounter DWORD -1    ;used to determine when the requestSignedFloats subroutine should stop accepting input.     
prompt BYTE "Please enter a value: ",0 


.CODE 

main PROC 

    call requestSignedFloats 
    exit 

main ENDP 

requestSignedFloats PROC 

    finit         ;initializes floating point unit 
    push edx       ;pushes the original value of edx onto the stack. This will be popped when the subroutine ends. 
    mov  edx, OFFSET theSFPArray  ;moves the offset of theSFPArray into edx so that values can be placed into it. 
    push edx       ;pushes edx onto the stack while it contains the offset of the SFPArray for later usage. 

    mov eax,100 
    push eax 
    fild dword ptr [esp]     ;get the 100 from memory and throw it onto the FPU, into ST(0) 
    fchs         ;changes the 100 in ST(0) into -100 
    pop eax     

L1: 
    mov  edx,OFFSET prompt       
    call WriteString     ;displays the String within the prompt variable on the screen.   
    call ReadFloat      ;requests a float as input from the user and stores it at the top of the floating point stack, aka ST(0). 
    fcom         ;compares the value in ST(1) to the value in ST(0). 
    jae  L2 
    pop  edx       ;this line and the two lines below it will execute if the comparison dictates that ST(1) is below the value in ST(0). This should cause the subroutine to end. 
    pop  edx       ;a second pop of edx is necessary to restore edx to its original value since two alterations of edx were placed onto the stack at the beginning of the subroutine. 
    mov  lengthOfSFPArray,LENGTHOF theSFPArray ;Moves the current number of values stored in theSFPArray into the lengthOfSFPArray variable. 
    mov  eax,lengthOfSFPArray   ;Returns in eax,the number of values in the array, as specified by the requirements 
    ret 
L2: 
    fstp tempStoreFP     ;pops the user input value off of the stack temporarily so that fchs can be used to change the sign of the value in ST(0) 
    fchs         ;changes the -100 in ST(0) into a positive 100. 
    fld  tempStoreFP     ;pushes tempStoreFP back onto the stack so that its value is now in ST(1) 
    fcom  
    jbe  L3 
    pop  edx       ;this line and the two lines below it will execute if the comparison dictates that ST(1) is below the value in ST(0). This should cause the subroutine to end. 
    pop  edx       ;a second pop of edx is necessary to restore edx to its original value since two alterations of edx were placed onto the stack at the beginning of the subroutine. 
    mov  lengthOfSFPArray,LENGTHOF theSFPArray ;Moves the current number of values stored in theSFPArray into the lengthOfSFPArray variable. 
    mov  eax,lengthOfSFPArray   ;Returns in eax,the number of values in the array, as specified by the requirements 
    ret 
L3: 
    pop  edx       ;this is done to pop the offset of theSFPArray off of the stack and back into edx since at this point edx still stores the "prompt". 
    inc  inputLoopCounter    ;increments inputLoopCounter so that its value is equal to the index that the number input by the user will be stored in. 
    mov  ecx,inputLoopCounter   ;uses inputLoopCounter to determine how many times the loop will execute. 
R1: 
    inc  edx       ;increments edx an amount of times equivalent to the value stored in inputLoopCounter. 
    loop R1 
    fstp qword ptr [edx]    ;takes the value at the top of the stack and stores it as a REAL8 at the address specified by edx (aka its array index) 
    mov  lengthOfSFPArray,LENGTHOF theSFPArray ;Moves the current number of values stored in theSFPArray into the lengthOfSFPArray variable. 
    fchs         ;changes the 100 in ST(0) to a -100 in preparation for the next iteration of the subroutine. 
    cmp  inputLoopCounter,10 
    je  L4 
    jmp  L1       ;An unconditional jump to L1 that causes this subroutine to execute repeatedly. The line above this one prevents it from being an infinite loop. 
L4: 
    mov  eax,lengthOfSFPArray   ;Returns in eax,the number of values in the array, as specified by the requirements 
    pop  edx       ;if the program makes it to this point, the offset of the array would have been popped off of the stack, meaning the original value of edx is the only thing 
              ;remaining on the stack, so only one pop is necessary 
    ret 

requestSignedFloats ENDP 

Antwort

5

In Ihrem .data Abschnitt definieren Sie lengthOfSFPArray wie diese

lengthOfSFPArray DWORD ?    ;this variable will store the length of theSFPArray. This value will be used to determine if requestSignedFloats should stop looping. 

Die ? bedeutet, dass der Anfangswert ist nicht definiert und daher zwischen 0 und 2^32-1.

In L1 Sie abrufen, dass undefined Wert mit

mov  eax,lengthOfSFPArray   ;Returns in eax,the number of values in the array, as specified by the requirements 

So EAXundefined sein wird oder was auch immer Wert lengthOfSFPArray bei der Initialisierung hatte. Sie wiederholen das in L2.

In R1 gesetzt Sie lengthOfSFPArray mit

mov  lengthOfSFPArray,LENGTHOF theSFPArray 

zum LENGTHOF von theSFPArray, definiert in der data Abschnitt als

theSFPArray REAL8 10 dup(?) 

die per Definition ist die Anzahl der Elemente in der theSFPArray: LENGTHOF(theSFPArray) = 10.

Danach, vergleichen Sie den Wert von 10 auf den Wert von 10, die immer TRUE ist:

cmp  lengthOfSFPArray,10 
je  L4      ; ALWAYS jump to L4 
jmp  L1      ; NEVER reached 

L4: ist Ihr Aussprunglabel, so dass das gesamte Verfahren wird nur einmal ausgeführt.

+0

Nur um sicherzustellen, dass ich richtig verstehe, sagst du, dass die Zeile: "theSFPArray REAL8 10 dup (?)" Bewirkt, dass dasSFPArray nicht nur 10 Indizes hat, sondern 10 Indizes mit 10 undefinierten Elementen, und das ist der Grund die Zeile: "cmp lengthOfSFPArray, 10" ist immer wahr? – Proto

+1

@Proto: 'lengthOfSFPArray' ist auf' LENGTHOF theSFPArray' gesetzt. Die 'LENGTHOF'-Direktive [Gibt die Anzahl der Elemente in der Array-Variablen zurück.] (Http://www.phatcode.net/res/223/files/html/Chapter_8/CH08-5.html) Wegen der _number of items_ in' theSFPArray REAL8 10 dup (?) 'ist 10 per Definition' LENGTHOF theSFPArray' gibt 10 zurück.Und wenn Sie "lengthOfSFPArray" = 10 bis 10 vergleichen, erhalten Sie immer "TRUE". Die Zeile: "theSFPArray REAL8 10 dup (?)" Hat genau 10 Einträge (und ** keine Indizes **), sondern 80 Bytes. 'LENGTHOF' gibt die Anzahl der Elemente zurück. Um die Anzahl der BYTEs zu erhalten, müssten Sie 'SIZEOF' verwenden. – zx485

+0

Ich habe meinen ursprünglichen Post mit meinem Code nach den leichten Änderungen aktualisiert, die ich gemacht habe, dass ich dachte, würde die Probleme lösen, die Sie erwähnten, aber es scheint immer noch nicht zu funktionieren. Ich fügte Zeilen in L1 und L2 hinzu, die LENGTHOF theSFPArray in die lengthOfSFPArray-Variable verschieben. Außerdem habe ich die cmp-Zeile in R1 basierend auf der Variable inputLoopCounter anstelle der lengthOfSFPArray-Variable erstellt. Gibt es etwas, das ich nicht richtig verstehe? – Proto