1

When adding a WriteDec and CRLF calls under a recursive procedure, it goes into an infinite loop.

  1. My motivation is to print out each time the value of eax and crlf right after the right shift.
  2. When reaching 0, it appears that there are infinite recursive calls because it keeps on printing 0's.
  3. I was under the impression that it shouldn't be the case since ZF = 1 first time eax = 0 and therefore it jumps to skip label which ends the recursion.

The following code causes an infinite loop when EAX register = 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

Expected result:

5
2
1
0
1
2
5 
10
0

1 Answer 1

2

The culprit is here:

mov [ebp-4], eax
jz skip

In x86, the MOV instruction does not set any flags, so JZ would take the state of the ZF flag left over from that function call above.

The correct code is as follows:

mov [ebp-4], eax
test eax, eax
jz skip
Sign up to request clarification or add additional context in comments.

5 Comments

Thank you @hidefromkgb, since shift right triggered ZF when performed after eax = 1, I was under the impression the jz skip will be done even though it was after the mov [ebp-4], eax. Can I only use the flags right after an appropriate command that sets them to 0/1 ?
@Tom.A The state of the EFL register stays the same until some flag-altering command clobbers it. In general, it is not safe to assume that the third-party functions you call leave EFL as it was, for inside there may be commands like ADD or XOR or whatever.
@Tom.A And BTW, are you absolutely sure that the functions you call don`t clobber EAX as well?
it clobbers eax but there isn't any issue after adding either your suggestion or cmp eax, 0 jz skip before the mov command
@Tom.A: and hidefrom: No, WriteDec does not overwrite EAX; it has no return value. Irvine32 functions don't destroy (clobber) any registers except their return value (if any). (Unlike the standard library calling convention where EAX, ECX, and EDX are all call-clobbered). But apparently Irvine32 functions are allowed to clobber EFLAGS. (That link is to google's webcache because the normal site is down currently.)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.