嘿,我知道我一直在问很多问题..但是谷歌这方面的资源不多,所以希望这将有助于未来尝试做类似项目的人,我总是谷歌解决方案,但我从来没有搜索过第一页。
我看着Alex发布的英特尔手册,对我来说似乎很陌生 http://www.intel.com/content/www/us/en/architecture-and-technology/64-ia-32-architectures-software-developer-vol-2a-2b-instruction-set-a-z-manual.html
所以我想我知道一个简单的DIV
操作码是如何工作的。因为它毕竟只是divide
。
我添加ADD
,SUB
没有任何困难,当然IMUL
有问题,你们帮我解决了那个问题。在难度方面,似乎DIV
与IMUL
属于同一类别。
没有使用手册只是使用OllyDbg进行自我调试测试。
我发现除法的答案总是存储在EAX
中。弄清楚剩下的人也知道谁存储在EDX
中。
从研究这个算法非常重要的人知道,有人会使用随机数除法的余数来生成0-10非常聪明的转换..但仍然是我的问题。
这已经很奇怪我从未想过被分割的十六进制数字会有剩余的小数点甚至不属于它们。
DIV ECX
就像
regs.d.eax /= regs.d.ecx;
regs.d.edx = regs.d.eax % regs.d.ecx;
我在考虑可能先把剩余的东西放在第一位......简直就是这样。
regs.d.edx = regs.d.eax % regs.d.ecx;
regs.d.eax /= regs.d.ecx;
好吧,我几乎不能使用数学编程,所以对我来说有点困惑。我更像是一个将结果存储在一个字符串然后用小数点分割的人,这就是我如何得到剩余部分是的,我知道它很慢而且它正在走出简单的路径......我自己反对使用字符串数学代码中的操作。
好吧..看看我放在那里的C代码..可能必须在临时变量中进行除法之前存储EAX
和ECX
..或者首先执行余数代码..然后除法典第二。我不知道。
好吧,我会看到也许你们可以给我一个更好的答案,也许它不可能在一行中完成,但也许我犯了一些错误......我无法真正测试我现在做的事情,因为很多在我甚至可以编译软件之前,我必须解决其他问题。
答案 0 :(得分:2)
这些手册不容易阅读,但是他们对你的问题都有答案(好吧,大多数,文档中偶尔会有遗漏和错误)。
您猜测的算法中缺少的一件事是DIV通常将2N位除以N位,也就是说,当您执行DIV ECX
时,您将EDX中包含的64位无符号值除以EAX: ECX中的32位无符号值。然后将商存储在EAX中,其余部分存储在EDX中。
你还应该记住除法溢出的可能性(在这种情况下,EDX> = ECX是它的条件)和指令在EFLAGS寄存器中修改的标志。
答案 1 :(得分:0)
我认为合理公平的翻译将是:
int16_t a=42,b=7;
int16_t div = a/7;
int16_t remainder = a - (div*b);
在实践中,此可能或可能不等同于remainder = a % b
(我需要查找标准规范)。如果仔细考虑负数会发生什么,它会变得更有趣。
所有这一切,小数点从未发挥作用,所以我不明白为什么你在帖子中提到它。
也许不能在一行中完成 [...]
我非常怀疑编译器将重新使用子表达式,并在适用时自动使用(E)DX中的余数。 (这对于编译器而言是相当简单的优化)