【问题标题】:Assembly Code to C, what are the arguments in the C code that will make the Assembly code汇编代码到 C,C 代码中将生成汇编代码的参数是什么
【发布时间】:2021-07-18 03:24:12
【问题描述】:

所以我刚刚注册了这个在线课程,这是我第一次作业的一部分,我已经在汇编代码中找到了缺失的部分并且已经走到了这一步。

这是汇编代码:

0x08048394 <call1+0>:  push   %ebp
0x08048395 <call1+1>:  mov    %esp,%ebp
0x08048397 <call1+3>:  sub    $0x10,%esp
0x0804839a <call1+6>:  mov    %ebx,(%esp)
0x0804839d <call1+9>:  mov    %esi,0x4(%esp)
0x080483a1 <call1+13>: mov    0x8(%ebp),%edx
0x080483a4 <call1+16>: mov    0xc(%ebp),%ecx
0x080483a7 <call1+19>: mov    (%ecx,%edx,4),%eax
0x080483aa <call1+22>: mov    0x10(%ebp),%ebx
0x080483ad <call1+25>: mov    (%ebx,%edx,4),%esi
0x080483b0 <call1+28>: cmp    %esi,%eax
0x080483b2 <call1+30>: jle    0x80483b9 <call1+37>
0x080483b4 <call1+32>: mov    %eax,(%ebx,%edx,4)
0x080483b7 <call1+35>: jmp    0x80483be <call1+42>
0x080483b9 <call1+37>: mov    %esi,(%ecx,%edx,4)
0x080483bc <call1+40>: mov    %esi,%eax
0x080483be <call1+42>: pop    %ebx
0x080483bf <call1+43>: pop    %esi
0x080483c0 <call1+44>: add    $0x8,%esp
0x080483c3 <call1+47>: leave
0x080483c4 <call1+48>: ret

我的问题是,下面的 C 代码 sn-p 中的哪些参数会导致上面的汇编代码:

int main(){

int a1[] = {10, 12, 3, 4, 25};

int a2[] = {9, 28, 7, 16, 5};

call1(_________________________________);

}

我认为它只是 a1 和 a2,但我不确定这就是我需要帮助的原因。 在我看来,这个汇编代码可能只是在交换两个数组的值...... 我是对的,还是完全不对?

【问题讨论】:

  • 没有弄清楚整个事情,但你有 3 个相对于 (%ebp) 的正偏移量,所以我想说那个函数有三个参数。
  • 该函数似乎也有一个返回值设置为call+40eax 被分配了一些东西。
  • 这个问题的格式不正确:“以下 C 代码 sn-p 中的哪些参数会导致上面的汇编代码?” - 任何参数都会导致该代码.那是函数本身的代码,无论你传递什么参数,它总是一样的。如果你想弄清楚传递了哪些参数,你需要查看调用者的汇编代码(main)!
  • 可悲的事实是,您无法从这个 asm 源中分辨出来。您需要编码main。你可以做出明智的猜测,但仅此而已。比如,两个参数显然是指针,你可以猜到它们可能是a1a2,但你不知道哪个是哪个,它们也可以是a1 + 3 之类的东西,甚至完全不相关。代码中也没有循环,所以它显然没有处理整个数组。您还可以看到第一个参数用作索引但您不知道值。
  • 阅读这篇描述 C 调用约定要求调用者和被调用者做特定事情的文章你可能会有所收获:en.wikipedia.org/wiki/X86_calling_conventions

标签: arrays c assembly x86 att


【解决方案1】:

正如我在上面的评论中所说,这个问题的格式不正确:“以下 C 代码 sn-p 中的哪些参数会导致上述汇编代码?” - 任何参数都会导致到那个代码。那是函数本身的代码,无论你传递什么参数,它总是一样的。如果你想弄清楚传递了哪些参数,你需要查看调用者的汇编代码(main)。

但是,即使没有main的完整代码,通过你拥有的C源代码和函数的汇编我们可以推断出以下内容:

  1. 函数传递了 3 个参数,我们可以看到它引用了 0x8(%ebp)0xc(%ebp)0x10(%ebp)。这些参数的顺序是第一、第二和第三。

  2. 第一个参数(从ebp 偏移0x8)被用作索引,我们可以从:

    mov    0x8(%ebp),%edx
    mov    0xc(%ebp),%ecx
    mov    (%ecx,%edx,4),%eax
    
  3. 其他两个参数(偏移量0xc0x10)被视为指向数组的指针并使用第一个进行索引。

鉴于上述情况,代码的公平重构如下:

int call1(int index, int *a1, int *a2) {
    int eax, esi;

    eax = a1[index];
    esi = a2[index];

    if (eax <= esi) {
        a1[index] = esi;
        eax = esi;
    } else {
        a2[index] = eax;
    }

    return eax;
}

在我看来,这段汇编代码可能只是在交换两个数组的值……我是对的,还是完全不对?

是的,这对我来说似乎是正确的。当然实际上我们不知道实际传递给函数的是什么,但如果在main 中进行的调用如下:

call1(some_index, a1, a2);

然后该函数获取a1a2 和一些索引,并检查给定索引处a1 的元素是否小于或等于同一索引处a2 的元素。如果是,则第一个元素被第二个元素覆盖,否则第二个元素被第一个元素覆盖。在任何情况下,该函数都会返回最大元素的值。

请注意,我们实际上不知道传递的第一个参数是a1 还是a2。它可以是任何一种方式,甚至可以是a1 + somethinga2 + something_else。确切的参数是什么只能通过查看main的完整代码(C或汇编)来确定!

【讨论】:

  • 非常感谢您的故障,我真的很感激。我最初只能看到交换正在发生,但看不到它是如何完成的。我看到你使用了指针,有什么特别的原因吗?程序集中的东西暗示了指针?
  • @Struggle_Bus 好吧,是的,这个:mov (%ecx,%edx,4),%eax 是给定指针的数组(4 字节元素)的经典索引。在这种情况下,指针将位于 ecx 中,索引位于 edx 中。
  • 好吧,这是有道理的。非常感谢您对理解这一点的帮助!
猜你喜欢
  • 2012-03-04
  • 2011-08-27
  • 2018-05-07
  • 2011-06-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-10
  • 1970-01-01
相关资源
最近更新 更多