汇编如何将操作码DIV转换为C代码

汇编如何将操作码DIV转换为C代码,c,assembly,x86,machine-code,code-translation,C,Assembly,X86,Machine Code,Code Translation,嘿,我知道我问了很多问题。。但在谷歌上没有太多的资源,所以希望这能帮助未来尝试做类似项目的人,我也一直在谷歌解决方案,但我从来没有搜索过第一页 我看了Alex发布的英特尔手册,对我来说似乎很陌生 所以我想我知道一个简单的DIV操作码是如何工作的。因为它毕竟只是一个除法。 我在添加ADD,SUB时没有遇到任何困难,当然IMUL在那个问题上你们帮了我的忙。就难度而言,DIV与IMUL属于同一类 不用使用手册,只需使用OllyDbg进行自调试测试 我发现除法的答案总是存储在EAX中。计算出的剩余部分

嘿,我知道我问了很多问题。。但在谷歌上没有太多的资源,所以希望这能帮助未来尝试做类似项目的人,我也一直在谷歌解决方案,但我从来没有搜索过第一页

我看了Alex发布的英特尔手册,对我来说似乎很陌生

所以我想我知道一个简单的
DIV
操作码是如何工作的。因为它毕竟只是一个除法。 我在添加
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
。。或者先执行剩余的代码。。然后是除法代码。我不知道


好吧,我会看看,也许你们能给我一个更好的答案,也许这不能在一行完成,但也许我犯了一些错误。。我无法真正测试我现在所做的事情,因为在我编译软件之前,我还需要解决许多其他问题。

我认为一个合理公平的翻译应该是:

  int16_t a=42,b=7;
  int16_t div = a/7;
  int16_t remainder = a - (div*b);
实际上,这可能等于,也可能不等于
余数=a%b
(我需要查找标准规范)。如果你仔细考虑负数发生了什么,它会变得更有趣。< /P> 尽管如此,小数点永远不会起作用,所以我不明白你为什么在帖子中提到它

也许这不能一行完成[…]


我高度怀疑编译器会重新使用子表达式,并在适用时自动使用(E)DX中的剩余部分。(对于编译器来说,这是一个相当琐碎的优化)

这些手册不容易阅读,没错,但它们对您的问题都有所有的答案(好吧,大多数,文档中偶尔会有遗漏和错误)

猜测算法中缺少的一点是DIV通常将2N位除以N位,也就是说,当您执行
DIV ECX
时,将EDX:EAX中包含的64位无符号值除以ECX中的32位无符号值。商然后存储在EAX中,其余的存储在EDX中


您还应该记住除法溢出的可能性(在这种情况下,EDX>=ECX是它的条件)以及指令在EFLAGS寄存器中修改的标志。

这一算法中发生的事情可不是开玩笑的
DIV ECX
MOV EDI,EDX
CMP EDI,4
JNZ SHORT XXXXXXX
它只是利用剩余部分工作。没有关系。。我想我们现在谈论的是不同的事情<“英特尔手册”中的“代码>除法”仅为无符号除法。。。所以我永远不会担心负数。DIV执行无符号除法。int16_t是有符号类型,因此您的示例进行有符号除法。另外,根据C标准,.I不知道您的ADD/ADC/SUB/SBB是否正确地设置了标志(SF、CF、OF、AF、PF;ZF是微不足道的)。我现在正试图避开他们。我说我只有寄存器,我注意堆栈,它是一个由65k元素组成的字节数组。大会上堆满了让我困惑的东西。。但是我倾向于避免这些事情,呵呵。像
cHao
告诉我的
ret0/RET
只返回函数的返回地址,这样它就知道返回到哪里了。。我真的需要这个吗?我的函数将返回C/C++函数的工作方式,因此它是无用的,可能与标志相同。如果我现在不使用标志时遇到问题,我将查看。请告诉我,我必须使用除模数(%)之外的其他方法来获得始终与汇编中相同的余数。我将设置一个测试1,以强制获取所有80亿个除法,并记录real assembly的所有余数,然后在emulator上进行相同的测试,以查看是否有任何错误。如果您的E*X成员未签名,您可以使用/和%获取未签名除法,就像使用DIV一样。但您仍然需要在此处执行64位除法。这样做:
unsigned long-long-divident=(unsigned long-long)…EDX+…EAX
然后
…EAX=(32位无符号类型)(被除数/…ECX)
…EDX=(32位无符号类型)(股息%…ECX)无符号长除数=(无符号长)regs.d.edx+regs.d.eax
regs.d.eax=(有符号整数)(股息/regs.d.ecx)
regs.d.edx=(有符号整数)(股息%regs.d.ecx)我使用VisualStudio,所以长度应该是64位。但是寄存器eax、edx均未签名。。我把签名传给他们。有点困惑。。但我想我会留下它。@SSpoke:long=32位,在VisualStudio中。不要删除第二个长(
long
在C中至少为64位,而
long
至少为32位)或使用
\u int