【问题标题】:Assembly How to convert REP STOS to C code汇编 如何将 REP STOS 转换为 C 代码
【发布时间】:2011-12-07 11:51:11
【问题描述】:

我已经调试了一段时间REP STOS DWORD PTR ES:[EDI]

根据我的结论,它总是使用

ECX 作为计数器。 EAX 作为将被复制到 EDI 然后附加 ECX 次的值 所以在放入EDI的尖头转储之后

它似乎用什么覆盖了 EDI 中的指向数据 似乎它总是只使用 ECX 作为计数器,同时将 EDI 更改 4 个字节。 当计数器达到 0 时它停止工作

所以我想出了这种代码

while(regs.d.ecx != 0)
{
    *(unsigned int *)(regs.d.edi) = regs.d.eax;
    regs.d.edi += 4;
    regs.d.ecx--;
}

似乎可行.. 但我很担心,因为我只是靠运气和猜测工作做到了这一点。坚固吗?就像它总是ECX 作为计数器,EAX 作为数据,它总是复制 4 个字节,永远不会少?

【问题讨论】:

  • 发现重复的 stackoverflow.com/questions/3818856/what-does-this-assembly-do 有点晚了.. 似乎一切都有效。
  • 我建议您获取 AMD 的程序员手册(第 1 卷用于介绍,第 3 卷用于通用说明)以及英特尔的。不知何故,我更喜欢 AMD 的结构和表格。英特尔的似乎更详细一些。

标签: c assembly x86 machine-code code-translation


【解决方案1】:

你几乎是正确的。唯一的区别是方向标志 (DF) 控制是否从 EDI 中添加或减去 4(它实际上是从 ES 段基数偏移,但您可能不在乎):

for (; regs.d.ecx != 0; regs.d.ecx--)
{
    *(unsigned int *)(regs.d.edi) = regs.d.eax;
    regs.d.edi += regs.eflags.df ? -4 : 4;
}

注意for (; regs.d.ecx != 0; regs.d.ecx--) { }REP前缀的动作,循环体是STOS DWORD...的动作。

由于您提出了很多此类问题,我认为您会发现Intel 64 and IA-32 Architectures Software Developer’s Manual, Volumes 2A and 2B 很有用。这些包含每条指令和前缀的描述,包括伪代码描述。

【讨论】:

  • 不只是 DF。根据 CPU 模式,STOSD 可能需要也可能不需要操作数大小前缀 (66h),它控制元素大小(16 位与 32 位,还有 AX 与 EAX),地址大小前缀 (67h),它控制元素大小使用 EDI 和 ECX 位(16 对 32)。最后,它使用 ES 段寄存器,这意味着虚拟地址是 ES.base + (E)DI。哦,当然,如果内存无法写入(只读或未映射,或者如果启用页面转换,段或底层页面的权限(CPL 和 RPL)不足,则它当然可能会导致异常)。 :)
  • 等等,我什至不明白标志是如何从这个生成的......好吧,我的模拟器甚至没有标志......到目前为止一切都很好! :P,希望堆栈 + 寄存器就足够了
  • @SSpoke: EFLAGS 可以建模为另一个寄存器,其中一些位由其他指令设置。对于 DF 标志,有特定的说明 - STD 设置它,CLD 清除它。
猜你喜欢
  • 2020-11-04
  • 2014-09-01
  • 1970-01-01
  • 2011-05-04
  • 2011-12-07
  • 2013-01-22
  • 2013-04-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多