【发布时间】:2021-03-04 15:02:17
【问题描述】:
我正在编写一个代码生成问题,其中输出是 x86/64 汇编代码文件。我有以下输出序列
mov -0x8(%rbp), %r10 // r10 = 0 at the moment
mov $0xa, %r11 // r11 = 10
cmp %r11, %r10
setg -0x10(%rbp) // -0x10(%rbp) = 0
mov -0x10(%rbp), %r10 // %r10 is desired to be 0, but here is the problem
根据调试器,r10 设置为r10 0x100000000 4294967296
我不明白为什么 %r10 的内容没有设置为期望值0
有什么我错过的约定吗?
整个生成的 x86/64 程序是
.text
.globl _f1
_f1:
pushq %rbp
movq %rsp, %rbp
subq $16, %rsp
movq %rdi, -8(%rbp)
jmp f1.start
.text
f1.start:
movq -8(%rbp), %r10
movq $10, %r11
cmpq %r11, %r10
setg -16(%rbp)
movq -16(%rbp), %r10
cmpq $1, %r10
je f1.then
jmp f1.end
.text
f1.then:
movq $1, %rax
movq %rbp, %rsp
popq %rbp
retq
.text
f1.end:
movq $0, %rax
movq %rbp, %rsp
popq %rbp
retq
.text
.globl _f2
_f2:
pushq %rbp
movq %rsp, %rbp
subq $16, %rsp
movq %rdi, -8(%rbp)
jmp f2.start
.text
f2.start:
movq -8(%rbp), %r10
movq $10, %r11
cmpq %r11, %r10
setg -16(%rbp)
movq -16(%rbp), %r10
cmpq $1, %r10
je f2.then
jmp f2.end
.text
f2.then:
movq $1, %rax
movq %rbp, %rsp
popq %rbp
retq
.text
f2.end:
movq $0, %rax
movq %rbp, %rsp
popq %rbp
retq
.text
.globl _main
_main:
pushq %rbp
movq %rsp, %rbp
subq $40, %rsp
movq $0, %rdi
callq _f1
movq %rax, -24(%rbp)
movq $15, %rdi
callq _f2
movq %rax, -32(%rbp)
movq -24(%rbp), %r10
movq -32(%rbp), %r11
addq %r10, %r11
movq %r11, -40(%rbp)
movq -40(%rbp), %rax
movq %rbp, %rsp
popq %rbp
retq
您可以将其保存到test.s,并通过运行以下命令生成可执行文件
clang -Wno-override-module -O1 -Wall -fno-asynchronous-unwind-tables -mstackrealign -o test test.s
【问题讨论】:
-
setg设置单个字节。但是,您继续阅读整个 qword。你确定这是正确的吗? -
为什么要在这里费心记忆呢?
setg %r10b设置 R10 的低字节。最好在比较之前用xor %r10d, %r10d将完整的R10 归零之后。或者之后使用movzbl %r10b, %r10d将零扩展到完整的注册,尽管更糟糕的是especially within the same register defeating mov-elimination。您可以使用即时比较,例如cmpq $0xa, -0x8(%rbp)。 -
无论如何,您的问题标题并没有反映问题。如果您使用调试器单步执行代码,您会看到
setg仅写入 1 个字节,根据手册 felixcloutier.com/x86/setcc。这是一个非常糟糕/不方便设计的指令指令,不幸的是 AMD64 没有修复。
标签: assembly compiler-construction x86-64 codegen