1

我很难理解案例 50、52 等是如何通过汇编语言确定的。

据我了解,跳转表对应于每种情况下要执行的操作,并且检查 edx > 5 表示该情况的范围从 0 到 5?我相信 1 被遗漏了,因为它是默认情况,但为什么 5 被遗漏了?

我觉得应该有一个案例55:结果* =结果,不是吗?

如果有人能帮忙解释一下,那就太好了。谢谢!

int switch_prob(int x) 
{
    int result = x;
    switch (x)
    {
        case 50:
        case 52:
            result <<= 2;
            break;
        case 53:
            result >>= 2;
            break;
        case 54:
            result *= 3;
            break;
        default:
            result += 10;   
    }
    return result;
}

图 3.38 显示了该过程的反汇编目标代码。我们只对第 4 行到第 16 行显示的代码部分感兴趣。我们可以在第 4 行看到参数 x(相对于 %ebp 的偏移量 8)被加载到寄存器 %eax 中,对应于程序变量结果。第 11 行的“lea 0x0(%esi), %esi”指令是插入的 nop 指令,以使第 12 行的指令从 16 的倍数的地址开始

跳转表位于不同的内存区域。使用调试器 GDB,我们可以使用命令 x/6w 0x8048468 检查从地址 0x8048468 开始的六个 4 字节内存字。GDB 打印以下内容:

(gdb) x/6w
0x8048468: 0x080483d5 0x080483eb 0x080483d5 0x0x80483e0
0x8048478: 0x080483e5 0x080483e8
(gdb)

汇编代码:

1: 080483c0 <switch_prob>:
2: 80483c0: push %ebp
3: 80483c1: mov %esp,%ebp
4: 80483c3: mov 0x8(%ebp),%eax // X is copied into eax ; eax = x
5: 80483c6: lea 0xffffffce(%eax),%edx // placeholder 
6: 80483c9: cmp $0x5, %edx // Compare edx (3rd argument) with 5; Edx - 5 // clearly, edx is x
7: 80483cc: ja 80483eb <switch_prob+0x2b> // if edx - 5 > 0, Jump into line 16 (default)
8: 80483ce: jmp *0x8048468(,%edx,4) // Go into the jump table
9: 80483d5: shl $0x2, %eax // eax << 2
10: 80483d8: jmp 80483ee <switch_prob+0x2e> // Jump to line 17
11: 80483da: lea 0x0(%esi),%esi // esi = esi  NOP. Filling in N bytes
12: 80483e0: sar $0x2, %eax // eax >> 2
13: 80483e3: jmp 80483ee <switch_prob+0x2e> // Jump to line 17
14: 80483e5: lea (%eax, %eax, 2), %eax // eax = eax + 2(eax)
15: 80483e8: imul %eax, %eax // eax *= eax
16: 80483eb: add $0xa, %eax // eax += 10
17: 80483ee: mov %ebp, %esp // esp = ebp
18: 80483f0: pop %ebp
19: 80483f1: ret
4

1 回答 1

4

The assembly does not match the source code. It matches something more like this:

int switch_prob(int x) 
{
    int result = x;
    switch (x)
    {
        case 50:
        case 52:
            result <<= 2;
            break;
        case 53:
            result >>= 2;
            break;
        case 54:
            result *= 3;
            // WARNING: Falls through
        case 55:
            result *= result;
            // WARNING: Falls through
        default:
            result += 10;   
            break;
    }
    return result;
}

This is likely caused by human error (e.g. updating the source code in the question so it's not identical to the question last year's students got, but forgetting to update the assembly to match).

Never assume teachers/professors are non-human...

于 2015-10-19T07:07:39.217 回答