Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Assembly x86汇编初学者:程序不';t循环正确吗?_Assembly_X86_Masm32_Irvine32 - Fatal编程技术网

Assembly x86汇编初学者:程序不';t循环正确吗?

Assembly x86汇编初学者:程序不';t循环正确吗?,assembly,x86,masm32,irvine32,Assembly,X86,Masm32,Irvine32,下面程序的目标是接受多达10个带符号的8字节浮点 在-100范围内的数字≤ X≤ 100作为用户的输入,并将其存储到数组中。使用ReadFloat-Irvine方法接收用户输入。如果输入了超出该范围的数字,则子例程应停止执行,并通过eax返回数组中当前值的数量。这只是描述程序应该做什么的一点上下文。我在这段代码中遇到的问题是,它在接受第一个值后没有正确地循环。我把它设置好了,这样它就可以检查输入的数字在L1中是否高于或等于-100,然后在L2中是否低于或等于100。如果数字超出该范围,子例程应停

下面程序的目标是接受多达10个带符号的8字节浮点 在-100范围内的数字≤ X≤ 100作为用户的输入,并将其存储到数组中。使用ReadFloat-Irvine方法接收用户输入。如果输入了超出该范围的数字,则子例程应停止执行,并通过eax返回数组中当前值的数量。这只是描述程序应该做什么的一点上下文。我在这段代码中遇到的问题是,它在接受第一个值后没有正确地循环。我把它设置好了,这样它就可以检查输入的数字在L1中是否高于或等于-100,然后在L2中是否低于或等于100。如果数字超出该范围,子例程应停止执行,但如果在该范围内,则应前进到L3和R1。在L3和R1中,数字被放入FPArray中的索引中,如果数组中的值小于10,则程序应无条件跳回L1进行进一步迭代。R1中的JMP命令就是问题所在。在输入一个数字后,当前状态的子例程将停止执行,我不知道为什么。有人能提供帮助吗

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

.data
部分中,您可以这样定义
lengthOfSFPArray

lengthOfSFPArray DWORD ?                ;this variable will store the length of theSFPArray. This value will be used to determine if requestSignedFloats should stop looping.
表示初始值未定义,因此介于0和2^32-1之间

L1中,您使用

mov     eax,lengthOfSFPArray          ;Returns in eax,the number of values in the array, as specified by the requirements
因此,
EAX
将是
undefined
或初始化时
lengthOfSFPArray
具有的任何值。在L2中重复该操作

R1中,您可以使用

mov     lengthOfSFPArray,LENGTHOF theSFPArray
至FPARRAY的
长度,在
数据
部分中定义为

theSFPArray REAL8 10 dup(?)
根据定义,它是
theSFPArray
LENGTHOF(theSFPArray)=10
中的元素数

然后,将10的值与10的值进行比较,该值始终为
TRUE

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

L4:是您的退出标签,因此整个过程只执行一次。

为了确保我理解正确,您是说:“theSFPArray REAL8 10 dup(?)一行导致theSFPArray不仅有10个索引,而且有10个索引填充了10个未定义的元素,这就是该行的原因:“cmp lengthOfSFPArray,10”始终为真?@Proto:`lengthOfSFPArray`设置为FPArray的
LENGTHOF
LENGTHOF
指令的原因是
FPArray中的项目数为8 10个(?)
根据定义是10,FPARRAY的长度返回10。如果将
长度FPARRAY
=10与10进行比较,您将始终得到
TRUE
。行:“theSFPArray REAL8 10 dup(?)正好有10个项目(而不是索引),但80个字节。
LENGTHOF
返回项目数。要获得字节数,您必须使用
SIZEOF
。我已经用我的代码更新了我的原始帖子,我做了一些我认为可以解决您提到的问题的轻微修改,但它似乎仍然不起作用。我在L1和L2中添加了移动L的行将FPARRAY插入lengthOfSFPArray变量中。此外,我在R1中根据inputLoopCounter变量而不是lengthOfSFPArray变量生成了cmp行。是否有什么我没有正确理解的地方?我删除了昨天的注释。今天我更彻底地查看了您的代码:您的堆栈和循环现在可以正常工作了l、 应该不会出现问题。但是,您使用的
FCOM
错误。如果您查看,您会发现
FCOM
设置了FPU状态字,而不是在比较后的
jae
jbe
指令中引用的CPU标志。可能的解决方案是使用设置CPU的
FCOMI
根据比较操作进行标记。希望这有帮助。将L1和L2中的fcom行替换为“fcomi ST(0),ST(1)后“,我测试了该程序,但它的行为异常。程序在接受第一个浮点数后不再停止执行,现在请求第二个浮点数。但是,在输入第二个浮点数后,程序总是会崩溃。我完全不知道那可能是什么原因。