1

I am trying to implement two indented loops as shown in the screenshot below. The debugger shows that r13 is equal to 0 and r14 is equal to 9. why then does it skip the JL instruction and goes straight to the mov r13, 0 instruction

I suspected that the inc instruction in the middle is responsible for this, but it doesn't make any sense because the bits of the flag is still unchanged

pop r10 ; contains the size of the array 
    pop rax ; address of the array in memory 
    mov r11, rax ; copy of the address from rax now

    mov r12, 0 ; int i 
    mov r13, 0 ; int j 

    dec r10

    i_loop: 
        mov r14, r10
        sub r14, r12
        j_loop:


            mov r8, [r11 + r13 * 8]
            mov r9, [r11 + r13 * 8 + 8]

            cmp r8, r9  
            jg swap

            back: 
            inc r13
            cmp r13, r14

            jl j_loop


        mov r13, 0
        inc r12
        cmp r12, r10
        jl i_loop


Mina Ashraf
  • 353
  • 1
  • 12
  • 5
    Do not post pictures of code. Please replace the pictures with plain text. I will retract my downvote once you have done so. – fuz Mar 14 '20 at 20:42
  • 1
    However you think you're examining FLAGS with GDB, you did it wrong. `inc` sets FLAGS other than CF. In GDB, use `layout reg`, or `info reg eflags` to have GDB decode it. Use `inc` then `cmp`/`jle` instead of `jl`. – Peter Cordes Mar 14 '20 at 20:59
  • @PeterCordes I edited it. I posted a screenshot to show you the debugger – Mina Ashraf Mar 14 '20 at 21:09
  • @MinaAshraf Cool! – fuz Mar 14 '20 at 21:16
  • If it's the same as the GDB session in the first screenshot, you never printed flags, only the GP integer register that `cmp` read. Anyway, it's not important *how* you were doing it wrong, except that your claim in the question that "the bits of the flag is still unchanged" is nonsensical and obviously not true (because `inc` is the problem, overwriting SF/OF which `jl` checks (and all other flags except CF). https://www.felixcloutier.com/x86/jcc and https://www.felixcloutier.com/x86/inc – Peter Cordes Mar 14 '20 at 21:32
  • Do a `dec r14` before the loop. Then you can switch those problematic instructions around in the most logical order. – Jongware Mar 14 '20 at 21:33
  • The code that was edited into the question is not the same as was in the screenshot, and does not have the same problem. – 1201ProgramAlarm Mar 14 '20 at 21:51

1 Answers1

3

The flags aka condition codes are a set of 1-bit registers.  The cmp instruction sets.    But many instructions besides cmp also set the condition codes, while still many others don't.  So, whenever you have some other instructions between the compare and branch, you should check the instruction set reference to see whether that instruction also sets the condition codes.  You should also be able to check that the condition codes — the 1-bit registers — in the debugger.  You'd see them set properly after the cmp, and then readjusted after the inc.


See also https://stackoverflow.com/a/3925620/471129 re: the inc instruction

and https://stackoverflow.com/a/5210401/471129 re: seeing flags in gdb - use info reg eflags or layout reg

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
Erik Eidt
  • 23,049
  • 2
  • 29
  • 53
  • 1
    In this particular case, you can use `lea r13, [r13+1]` to increment r13 without changing the flags. – prl Mar 14 '20 at 21:00
  • Thank you. I moved the inc instruction and it worked. Thank you for the flag tip – Mina Ashraf Mar 14 '20 at 21:12
  • 1
    @prl: that's less efficient than doing `inc` first and using `cmp/jle`, which is an option in this case. Keeping cmp/jcc together allows macro-fusion, so it's a good habit to keep them together whenever possible, if you can't avoid `cmp` entirely by using flags set by `inc`/`dec`. But yes, `lea` is a good way to do math without touching FLAGS. – Peter Cordes Mar 14 '20 at 21:28