1

I'm writing a compiler for a uni assignment, I'm currently emitting asm from an internal representation. I have the following representation for for (a = 1; a < 10; a++) do print a:

COPY a, 1                    // Copy 1 to a
LABEL label0                 // 
LT tmp0, a, 10               // Store in tmp0 the result of the expression a < 10
JUMP_FALSE label1, tmp0      // Jump to label1 if tmp0 is false
PRINT a                      //
ADD a, a, 1                  // Store in a the result of the expression a + 1
JUMP label0                  //
LABEL label1                 //

I am emitting the following asm for this, where both constants and variables are emitted as globals variables for orthogonality:

#a := 1
movl var_1(%rip), %eax
movl %eax, var_a(%rip)
.label0:
#EXPR_START tmp0 = a < 10
movl var_a(%rip), %eax
movl var_10(%rip), %edx
cmpl %eax, %edx
setl %al
movzbl %al, %eax
movl %eax, var_tmp0(%rip)
#EXPR_END
#jmpf label1, tmp0
movl var_tmp0(%rip), %eax
testl %eax, %eax
jne .label1
#Print a
movl var_a(%rip), %eax
movl %eax, %esi
leaq printf_int(%rip), %rdi
movl $0, %eax
call printf@PLT
movl $0, %eax
#EXPR_START a = a + 1
movl var_a(%rip), %eax
movl var_1(%rip), %edx
addl %edx, %eax
movl %eax, var_a(%rip)
#EXPR_END
#jmp label0
jmp .label0
.label1:

This seems to be comparing a <= 10, but I don't understand why. Isn't the cmpl and setl combo setting the value of %al as 1 if the result of the comparison was "less then"? Then shouldn't testl %eax, %eax be 1 while a < 10 and jne occur when a == 10? If my understanding is wrong, how can I store the result of a comparison in a register (1 if the comparison holds, 0 otherwise)?

Below is the full asm which can be compiled with gcc asm.s. The expected output is 1 2 3 4 5 6 7 8 9 the actual output is 1 2 3 4 5 6 7 8 9 10.

main:
pushq %rbp
movq %rsp, %rbp
#a := 1
movl var_1(%rip), %eax
movl %eax, var_a(%rip)
.label0:
#EXPR_START
movl var_a(%rip), %eax
movl var_10(%rip), %edx
cmpl %eax, %edx
setl %al
movzbl %al, %eax
movl %eax, var_tmp0(%rip)
#EXPR_END
#jmpf label1, tmp0
movl var_tmp0(%rip), %eax
movl $1, %edx
cmpl %eax, %edx
je .label1
#Print a
movl var_a(%rip), %eax
movl %eax, %esi
leaq _printf_int(%rip), %rdi
movl $0, %eax
call printf@PLT
movl $0, %eax
#EXPR_START
movl var_a(%rip), %eax
movl var_1(%rip), %edx
addl %edx, %eax
movl %eax, var_a(%rip)
#EXPR_END
#jmp label0
jmp .label0
.label1:
popq %rbp
ret
.text
.globl var_tmp1
.data
.size var_tmp1, 4
var_tmp1:
.long 0
.text
.globl main
.text
.globl var_1
.data
.size var_1, 4
var_1:
.long 1
.text
.globl var_a
.data
.size var_a, 4
var_a:
.long 0
.text
.globl var_10
.data
.size var_10, 4
var_10:
.long 10
.text
.globl var_tmp0
.data
.size var_tmp0, 4
var_tmp0:
.long 0
_printf_int:
.string "%d "
1201ProgramAlarm
  • 32,384
  • 7
  • 42
  • 56
Alex
  • 1,416
  • 4
  • 16
  • 42
  • You have coded `if (10 < a) goto label1`. You have swapped the operand order in the `cmp` and you have used `if (tmp0 == 1)` meaning `JUMP_TRUE` not `JUMP_FALSE`. – Jester Nov 15 '20 at 00:00

1 Answers1

4
movl var_a(%rip), %eax
movl var_10(%rip), %edx
cmpl %eax, %edx
setl %al

This will set %al to 1 if %edx is less than %eax, i.e. if 10 is less than a. That seems to be the opposite of what you wanted, so either interchange the operands of cmpl or else reverse your test (setge %al).

Part of the confusion may come from the fact that the assembler mnemonics were originally invented for Intel syntax, in which the source and destination for two-operand instructions are in the other order: mov dest, src instead of AT&T's movl %src, %dest. So in Intel syntax, cmp rx, ry ; setl rz would set rz if rx is less than ry, which matches the algebraic notation rx < ry. But for AT&T syntax this becomes cmpl %ry, %rx ; setl %rz which may look backwards. It may help to think of the second, "destination" operand as being the one that the predicate is "about": "set if %rx is less than %ry".

Nate Eldredge
  • 48,811
  • 6
  • 54
  • 82
  • Related answer about the condition order mismatch in AT&T syntax: https://stackoverflow.com/questions/2397528/mov-src-dest-or-mov-dest-src/60596999#60596999 – ecm Nov 15 '20 at 11:40