这个汇编代码将如何翻译成c?
在C中,我有以下结构:这个汇编代码将如何翻译成c?,c,assembly,x86,x86-64,att,C,Assembly,X86,X86 64,Att,在C中,我有以下结构: typedef struct _Node{ int data; struct _Node *left; struct _Node *right; } Node; 和以下汇编代码: .section .text .global _start _start: mov $8, %esi mov $A, %rdi call func movq $60, %rax movq $0, %rdi syscall
typedef struct _Node{
int data;
struct _Node *left;
struct _Node *right;
} Node;
和以下汇编代码:
.section .text
.global _start
_start:
mov $8, %esi
mov $A, %rdi
call func
movq $60, %rax
movq $0, %rdi
syscall
func:
pushq %rbp
movq %rsp, %rbp
cmp (%rdi), %esi
jne continue
mov $1, %eax
jmp finish
continue:
cmpq $0, 4(%rdi)
je next
pushq %rdi
mov 4(%rdi), %rdi
call func
pop %rdi
cmp $1, %eax
je finish
next:
cmpq $0, 12(%rdi)
je fail
pushq %rid
mov 12(%rdi), %rdi
call func
pop %rdi
cmp $1, %eax
je finish
fail:
mov $0, %rax
finish:
leave
ret
现在试着用C写,我有一个问题:
__long__ func ( Node *root, __int__ x){
if (root->data == __x__ )
return 1;
if (root->left != null)
if (_____??_____)
return ___ func(root->left, x)____;
if (root->right != null)
return ____func(root->right, x)____;
}
为什么我们彼此有两个if?如果left不为null,则汇编代码使用left子调用函数,并且不执行另一个条件检查(即cmp调用)。如果
成功,则返回第二个If
bool func(Node *nd, int x)
{
if (nd->data == x)
return true;
if (nd->left)
{
if (func(nd->left, x) == true)
return true;
}
if (nd->right)
return func(nd->right, x);
return false;
}
我之所以选择bool
,是因为它在这个函数的上下文中是有意义的,即使int
或long
或其他可能也是有效的。为什么要删除前面的问题?这似乎是相同的内容?它包含的图像非常糟糕,导致它失去了关注@ecm plus更改了一个little@stacker编辑您的解决方案是正确的。不要删除和重新发布。公平地说,这个问题在其当前状态下是合理的。它可能不应该被否决为对上一个问题做错事的惩罚/报复。我们真正丢失的只是结构缺少\uuuu属性((打包))
的注释,以及关于返回类型的注释。虽然现在我们可以看到它检查子调用的返回值,但我们可以看到它是32位类型,因此int
或无符号
,而不是bool
或long
。(或者如果它是long
,那么它就是在执行(int)func(root->left,x)==1
之类!)我们可以从cmp$1,%eax
中看到返回类型是32位整数。(或long
,如果((int)func(…)==1)
)在x86-64系统V(和Windows x64)中,允许返回寄存器在实际返回值之外的寄存器位中存在高垃圾。(与arg传递相同;clang在被调用方中依赖于此,GCC和clang都在调用方中执行。ICC不…)我仍然不明白为什么我们需要额外的条件…当左路径找到值时,使用了额外的条件,因此它不应该也在右路径中查找。可能是一个二叉树实现。@stacker:请注意,执行nd->right调用的下一步:
块在逻辑上仅等同于tailcall。它实际上是检查返回值是否为==1
,如果是,则返回该值,否则返回0
。因此它毫无意义地在func(nd->right,x)
返回值上分支。如果你试图用C语言来表示逻辑,你需要在If(nd->right)
块中,类似{int rv=func();
/If(rv==1)return rv;}
(否则会变成return false;
)的东西,这当然是毫无意义的,因为函数只能返回0或1。因此next:
块的asm可能会更有效:mov 12(%rdi),%rdi
/离开(清理堆栈)/测试%rdi,%rdi
/jnz func
(优化的尾调用),否则将转到xor%eax,%eax
/ret
。当然,具有完全优化的实际编译器会将尾部递归转换为循环并执行检查,只在左侧递归。如果只启用部分优化(gcc-O1),那么也不会得到优化的tailcall。