我需要家庭作业问题的帮助。我应该弄清楚这段代码运行后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
的东西。我无法弄清楚那是做什么的。
答案 0 :(得分:1)
你对test
和jg
的看法是对的。它确实循环直到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
等于1
而ecx
设为8
。
test
指令位于循环的开始处,并且在它指示执行循环的条件之后立即与指令一起。 test
指令会影响很多标记,但由于条件跳转为jg
,我们只关注ZF
,OF
和SF
。只有在jg
ZF=0
时SF=OF
分支ZF
。现在
ECX!=0
在OF
SF
将始终为零,同样适用于8
,因为lea
在二进制补码中大于零(更准确地说,8的最高有效位为0)。 第一个eax
指令将2*ecx
设置为lea
。第二个和最后一个eax
将edx
添加到ecx
并减少它。最后,sum(8, n = 1, n*2 -1) + 1
递减,指令指针设置为循环的开始。
象征性地写出:
{{1}}