0

I have to code some sort of compiler and it works quite good, but I have a problem with the semantic of an "is-greater-than" expression.

As example I want to return the smallest argument:

func mymin(x y)
  cond
    x>y then return y; end;
  end;
  return x;
end;

Conditional-Statements should return -1 if they are true (otherwise 0). Therefore I copy 0 into the destination register (here it's %rax). If the left operand is greater I copy -1 into %rax (with the conditional move). The comparison between -1 and the result of the condition (cmp $-1, %rax) ensures a jump if it's true (-1 - -1 = 0).

But it's just the opposite. so

mymin(2,3) = 3
mymin(1,0) = 1
// ...

What's wrong?!

    .text

    .globl mymin
    .type mymin, @function
mymin:
    movq %rsi, %rax
    # calculate greater one between %rdi and %rsi to %rax (reg & reg)
    movq $0, %rax
    movq $-1, %r10
    cmpq %rdi, %rsi
    cmovgq %r10, %rax
    cmp $-1, %rax
    jz cond_1
    jmp cond_2
cond_1:
    movq %rsi, %rax
    ret
    jmp cond_2
cond_2:
    movq %rdi, %rax
    ret
NaN
  • 3,501
  • 8
  • 44
  • 77
  • This syntax (AT&T) is the opposite of Intel's own documentation (see [what does the cmpq instruction do?](http://stackoverflow.com/questions/21440403/what-does-the-cmpq-instruction-do)). Switch the registers in `cmovgq %r10, %rax`? – Jongware Jun 08 '14 at 11:41
  • 2
    The registers should be switched in the `cmp` not the `cmov`. – Jester Jun 08 '14 at 11:46
  • @Jester: oops :) Yeah that's what I meant, in hindsight. Must've copied the wrong line. – Jongware Jun 08 '14 at 11:49
  • So I got the AT&T syntax right first time ? :) If so, I'll remove my provisional comment from the answer. – Jongware Jun 08 '14 at 12:14

1 Answers1

2

Per my comment (and @Jester's correction), if you find the opposite value gets stored, you may have mixed up "left" and "right' in the cmpq operation.

But.. here is another, shorter take: why use an intermediate flag at all?

.text

.globl mymin
.type mymin, @function

mymin:
    movq %rsi, %rax
    # calculate greater one between %rdi and %rsi to %rax (reg & reg)
    movq %rdi, %rax
    cmpq %rsi, %rdi
    cmovle %rsi, %rax
    ret

rax gets loaded with the first value rsi, and it's assumed this is the lesser value. Then, you compare rdi with rsi. If this is less or equal, write rdi into rax instead.

(Disclaimer: I don't like AT&T's odd syntax and so it's probable, nay, even likely, I made the same error as you. Untested.)

Jongware
  • 22,200
  • 8
  • 54
  • 100