汇编到C援助

use*_*231 4 c x86 assembly

我有一个任务,我需要将程序集转换为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
Run Code Online (Sandbox Code Playgroud)

C代码:

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

Isk*_*rak 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
Run Code Online (Sandbox Code Playgroud)

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

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
Run Code Online (Sandbox Code Playgroud)

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

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

    for (int mask = 1; mask; mask <<= n) {
        result ^= (mask & x);
    }
    return result;
}
Run Code Online (Sandbox Code Playgroud)

请注意,我已经删除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

由于移位整数类型或更多的位数是未定义的行为(并且一个字节足以表示32位数字上明确定义的移位),编译器没有义务在有用的情况下处理它因此,任何通过CL编译成轮班的东西都不需要打扰明确的掩盖.因此,没有必要在C'翻译'中显示一个明确的掩码,但由于这是一个作业,我衷心建议实际解释你的选择.

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

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

我不太确定你想解释什么,因为你已经排序了大部分东西(除了movl $-1, %edi初始化结果-1andl %esi, %eax不是添加)