【发布时间】:2021-02-26 13:53:48
【问题描述】:
我正在为 uni 赋值编写编译器,我目前正在从内部表示中发出 asm。我对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 //
我为此发出以下 asm,其中常量和变量都作为正交性的全局变量发出:
#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:
这似乎是在比较a <= 10,但我不明白为什么。 cmpl 和 setl 组合不是将 %al 的值设置为 1,如果比较的结果是“小于”?那么testl %eax, %eax 不应该是1 而a < 10 和jne 发生在a == 10 时?如果我的理解有误,如何将比较结果存储在寄存器中(如果比较成立则为 1,否则为 0)?
下面是可以用gcc asm.s 编译的完整asm。预期输出为1 2 3 4 5 6 7 8 9,实际输出为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 "
【问题讨论】:
-
您已编码
if (10 < a) goto label1。您已经交换了cmp中的操作数顺序,并且您使用了if (tmp0 == 1),这意味着JUMP_TRUE而不是JUMP_FALSE。