我有一个任务,我需要将程序集转换为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)
我这样开始:
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以下两种方式之一:
sall $2, %edx ;; left shift EDX by 2sall %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初始化结果-1而andl %esi, %eax不是添加)