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 汇编递归过程中的无限循环_Assembly_X86_Masm - Fatal编程技术网

Assembly 汇编递归过程中的无限循环

Assembly 汇编递归过程中的无限循环,assembly,x86,masm,Assembly,X86,Masm,在递归过程下添加WriteDec和CRLF调用时,它将进入无限循环 我的动机是在右移之后,每次打印eax和crlf的值 当到达0时,似乎有无限个递归调用,因为它一直在打印0 我的印象是,情况不应该如此,因为ZF=1第一次eax=0,因此它跳到跳过结束递归的标签 以下代码在EAX寄存器=0时导致无限循环 .code MAIN PROC mov ecx, 10 L1: push 10 call f1 call exitProcess main ENDP f1 PROC push e

在递归过程下添加WriteDec和CRLF调用时,它将进入无限循环

  • 我的动机是在右移之后,每次打印eax和crlf的值
  • 当到达0时,似乎有无限个递归调用,因为它一直在打印0
  • 我的印象是,情况不应该如此,因为ZF=1第一次eax=0,因此它跳到跳过结束递归的标签
  • 以下代码在EAX寄存器=0时导致无限循环

     .code 
    MAIN PROC
    
    mov ecx, 10
    
    L1:
    
    push 10
    call f1
    
    call exitProcess
    main ENDP
    
    f1 PROC 
    
    push ebp
    mov ebp, esp
    sub esp, 4
    mov eax, [ebp+8]
    shr eax, 1
    
    
    
    call WriteDec
    call CRLF
    
    mov [ebp-4], eax
    jz skip
    call f1
    
    skip:
    mov eax, [ebp+8]
    call WriteDec
    call CRLF
    
    ; ** comment out ** mov ebp, [ebp]
    mov esp, ebp
    pop ebp
    ret 4
    f1 ENDP
    
    END MAIN
    
    预期结果:

    5
    2
    1
    0
    1
    2
    5 
    10
    
    罪魁祸首在这里:

    mov [ebp-4], eax
    jz skip
    
    在x86中,MOV指令不设置任何标志,因此JZ将获取上述函数调用遗留的ZF标志的状态

    正确的代码如下:

    mov [ebp-4], eax
    test eax, eax
    jz skip
    

    谢谢@hidefromkgb,因为在eax=1之后执行右移时触发了ZF,所以我的印象是,即使是在mov[ebp-4],eax之后,也会执行jz跳过。我只能在将标志设置为0/1的适当命令之后使用标志吗?@Tom.A EFL寄存器的状态保持不变,直到某个标志更改命令将其删除。一般来说,假设您调用的第三方函数保持EFL不变是不安全的,因为里面可能有像ADD或XOR之类的命令。@Tom.A和顺便问一下,您是否绝对确定您调用的函数也不会影响EAX?它会影响EAX,但在添加您的建议或cmp EAX后没有任何问题,0 jz在mov之前跳过command@Tom.A:和hidefrom:否,不覆盖EAX;它没有返回值。Irvine32函数不销毁(关闭)任何寄存器,除非它们的返回值(如果有)。(与标准库调用约定不同,标准库调用约定中EAX、ECX和EDX都是调用阻塞的)。但显然,Irvine32函数被允许对EFLAG进行重击。(该链接指向谷歌的网络缓存,因为普通网站目前已关闭。)