汇编到C援助

时间:2013-10-29 01:10:47

标签: c assembly x86

我有一个分配,我需要将程序集转换为C.程序集是x86。我注释了组件并开始填写C中的空白但是我对一些事情有点迷失,有人可以帮忙吗?请解释不要只是给出我想要学习的答案。

大会:

x at %ebp+8, n at %ebp+12

1 movl 8(%ebp), %esi  //store x in esi
2 movl 12(%ebp), %ebx //store n in ebx
3 movl $-1, %edi      //result in edi
4 movl $1, %edx       //i of loop in edx
5 .L2:
6 movl %edx, %eax     //move edx to eax
7 andl %esi, %eax     //sum += 1 ...? i think
8 xorl %eax, %edi     //results = results ^ (i & x)
9 movl %ebx, %ecx     //store n in ecx
10 sall %cl, %edx     //shift edx by %cl (low byte of ecx)
11 testl %edx, %edx   //check if zeroed out
12 jne .L2            //jump to .L2 if flag
13 movl %edi, %eax    //move result to eax

C代码:

int loop(int x, int n) {
  int result = _______;
  int mask;
  for (mask = 1; mask != 0; mask = ______) {
     result ^= mask & x;
  }
  return result;
}

1 个答案:

答案 0 :(得分:5)

我是这样开始的:

movl 8(%ebp), %esi  ;; esi :=  x
movl 12(%ebp), %ebx ;; ebx :=  n
movl $-1, %edi      ;; edi := -1
movl $1, %edx       ;; edx :=  1
.L2:
movl %edx, %eax     ;; eax := edx
andl %esi, %eax     ;; eax &= esi (:= x) 
xorl %eax, %edi     ;; edi ^= eax
movl %ebx, %ecx     ;; ecx := ebx (:= n)
sall %cl, %edx      ;; edx <<= ecx & 0x000000FF
testl %edx, %edx    ;; set flags with edx & edx
jne .L2             ;; loop if not ZF
movl %edi, %eax     ;; eax := edi

并通过直接翻译进展到这一点,切割尽可能少的角落:

int x, n, foo = -1, bar = 1;

do {
    int baz = bar;
    baz &= x;
    foo ^= baz;

    int qux = n;
    bar <<= qux & 0xFF;
} while (bar);

// now do something with foo

然后通过删除不必要的临时变量,更改为更友好的循环形式,并添加函数体和return语句来达到此目的:

int func(int x, int n) {
    int result = -1;

    for (int mask = 1; mask; mask <<= n) {
        result ^= (mask & x);
    }
    return result;
}

请注意,我已经在左移中删除了n的低位字节。在评论中进行了一些讨论之后,我已经确定并添加了解释。 我们可以通过以下两种方式之一使用sal

  1. 立即,例如sall $2, %edx ;; left shift EDX by 2
  2. 通过CL转换,例如sall %cl, %edx ;; left shift EDX by the lower byte of ECX
  3. 由于移位整数类型或更多的位数是undefined behaviour(并且一个字节足以表示32位数字上明确定义的移位),编译器没有义务以有用的方式处理它,所以通过CL编译到转换的任何东西都不需要打扰显式屏蔽。因此,没有必要在C'翻译'中显示一个明确的掩码,但由于这是一个作业,我衷心建议实际解释你的选择。

    (感谢Peter Huene在评论中提出这一点。)

    您还可以从生成的C代码生成x86程序集,以查看所获得的内容。不要指望得到与你开始时完全相同的东西,而是将其作为一种学习方式。例如,您可以在我们的循环中检查<< n是否已编译到。像clang -O0 -S -mllvm --x86-asm-syntax=att filename.c这样的东西可以解决问题。

    我不太确定您要解释的是什么,因为您已经对大部分内容进行了排序(movl $-1, %edi初始化结果为-1andl %esi, %eax未添加)