x86汇编语言作业概率

时间:2013-08-11 19:48:28

标签: assembly x86

我需要家庭作业问题的帮助。我应该弄清楚这段代码运行后edx的值是什么。

0x40106e    <main+30>:      mov    $0x1,%edx
0x401073    <main+35>:      mov    $0x8,%ecx
0x401078    <main+40>:      test   %ecx,%ecx
0x40107a    <main+42>:      jg     0x40107e <main+46>
0x40107c    <main+44>:      jmp    0x40108a <main+58>
0x40107e    <main+46>:      lea    (%ecx,%ecx,1),%eax
0x401081    <main+49>:      lea    (%eax,%edx,1),%eax
0x401084    <main+52>:      lea    0xffffffff(%eax),%edx
0x401087    <main+55>:      dec    %ecx
0x401088    <main+56>:      jmp    0x401078 <main+40>
0x40108a    <main+58>:      // endpoint

既然是家庭作业,我真的不想知道答案和如何解决问题一样多。我弄清楚循环,但我想我得到了它。我认为test %ecx,%ecx循环直到%ecx递减到0.是吗?真正让我感到满意的是所有lea的东西。我无法弄清楚那是做什么的。

2 个答案:

答案 0 :(得分:1)

你对testjg的看法是对的。它确实循环直到ecx为零。

lea

我对AT&amp; T语法不是很熟悉,所以我会使用英特尔语法(我觉得更直观)。我希望它仍然可以理解。 (其中一个主要区别是英特尔语法将目标放在第一位。)

某些说明允许您从地址加载值:

mov eax, [esi]  ; load a DWORD from the address in ESI

您可以更改这些以添加偏移量:

mov eax, [esi + 4]  ; load a DWORD from four bytes after the address in ESI

允许使用寄存器,比例和偏移的某些组合:

mov eax, [esi + ecx * 4 + 16]  ; load a DWORD from (ECX * 4 + 16) bytes after the
                               ; address in ESI

这很方便;您无需手动计算有效地址。

lea代表“加载有效地址”。从本质上讲,它可以让你做这样的事情:

lea eax, [esi + ecx * 4 + 16]

不是将值加载到该位置的内存中,而是仅计算地址;换句话说:

EAX = ESI + ECX * 4 + 16

上面的lea指令汇编为4个字节。相比之下,对我来说最明显的方式是:

mov eax, ecx
shl eax, 2
add eax, esi
add eax, 16

...汇编为14个字节。

答案 1 :(得分:1)

正如icktoofay解释的那样,lea指令将edx寄存器设置为eax - 1。让我们一步一步地完成整个代码。

前两行将立即值移至寄存器,因此edx等于1ecx设为8

test指令位于循环的开始处,并且在它指示执行循环的条件之后立即与指令一起。 test指令会影响很多标记,但由于条件跳转为jg,我们只关注ZFOFSF。只有在jg ZF=0SF=OF分支ZF。现在

  • ECX!=0OF
  • 之前为零
  • SF将始终为零,同样适用于8,因为lea在二进制补码中大于零(更准确地说,8的最高有效位为0)。

第一个eax指令将2*ecx设置为lea。第二个和最后一个eaxedx添加到ecx并减少它。最后,sum(8, n = 1, n*2 -1) + 1 递减,指令指针设置为循环的开始。

象征性地写出:

{{1}}