Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
这个汇编代码将如何翻译成c?_C_Assembly_X86_X86 64_Att - Fatal编程技术网

这个汇编代码将如何翻译成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

在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
    
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。