【发布时间】:2020-02-11 13:49:45
【问题描述】:
我们今天遇到了崩溃,原因是以下 x86 程序集中的 idiv 指令中的算术异常。
mov r10d,DWORD PTR [rbp+0x70]
xor ecx,ecx
mov eax,r15d
test r10d,r10d
setle cl
cdq
idiv ecx
这是gdb中所有寄存器的值:
rax 0x64 100
rbx 0xaebc30 11451440
rcx 0x0 0
rdx 0x0 0
rsi 0x1 1
rdi 0xaebc88 11451528
rbp 0x7fa56809b840 0x7fa56809b840
rsp 0x7fa56effc080 0x7fa56effc080
r8 0x12 18
r9 0x100016a0000a72e 72059148816131886
r10 0x1 1
r11 0x0 0
r12 0x9e2bb8 10365880
r13 0x0 0
r14 0xaebc80 11451520
r15 0x64 100
rip 0x495ebb 0x495ebb
eflags 0x246 [ PF ZF IF ]
cs 0x33 51
ss 0x2b 43
ds 0x0 0
es 0x0 0
fs 0x0 0
gs 0x0 0
由于设置了零标志,setle cl 将 0 写入 ecx,这会导致除以零。我不明白的是如何首先设置零标志。 r10 的值为 1,所以据我所知 test r10d,r10d 应该取消设置它。 cdq 似乎没有修改它,所以我不确定这里发生了什么。
任何有更多 x86 经验的人都可以理解问题所在吗?需要更多信息吗?
【问题讨论】:
-
这个寄存器转储是从
idiv之前的(或者在GDB 捕获应该是同一件事的SIGFPE 之后)?是的,R10 = 1, R10D & R10D != 0 所以 ZF 应该被清除。因此r10d是NOT setle 在CL 中放置了0。 -
此代码设计为在 r10 > 0 时崩溃。因此,它确实做到了这一点也就不足为奇了。
-
我后来发现我太兴奋了查看程序集并错过了代码中明显的愚蠢错误。希望下次我能记住这一点......
标签: assembly x86-64 divide-by-zero