C程序转换到Linux上的汇编(x86_64)

时间:2016-06-16 14:45:06

标签: c linux assembly x86-64

我是汇编编程的新手(特别是x86_64)。我已将以下c程序翻译成汇编。

我理解了大部分代码,但我无法理解我已经注释掉的2条说明。

* stmnt 1 通过将 42 复制到其强大的 rax 注册内容低字?


注意:根据逻辑 stmnt 1 应在地址存储在 rax 42 >

addl $1,(%rax) 

可以解释那两条指令。


temp.c

    #include<stdio.h>

    int main()
    {
        int a=42,*ptr;

        ptr = &a;
        (*ptr)++;

        return 0;
    }

temp.s

        .file   "temp.c"
        .text
        .globl  main
        .type   main, @function
    main:
    .LFB0:
        .cfi_startproc
        pushq   %rbp
        .cfi_def_cfa_offset 16
        .cfi_offset 6, -16
        movq    %rsp, %rbp
        .cfi_def_cfa_register 6
        subq    $32, %rsp
        movq    %fs:40, %rax
        movq    %rax, -8(%rbp)
        xorl    %eax, %eax
        movl    $42, -20(%rbp)
        leaq    -20(%rbp), %rax
        movq    %rax, -16(%rbp)
        movq    -16(%rbp), %rax  
        movl    (%rax), %eax         ;  stmt 1
        leal    1(%rax), %edx        ;  stmt 2
        movq    -16(%rbp), %rax
        movl    %edx, (%rax)
        movl    $0, %eax
        movq    -8(%rbp), %rcx
        xorq    %fs:40, %rcx
        je  .L3
        call    __stack_chk_fail
    .L3:
        leave
        .cfi_def_cfa 7, 8
        ret
        .cfi_endproc
    .LFE0:
        .size   main, .-main
        .ident  "GCC: (Ubuntu 5.3.1-14ubuntu2.1) 5.3.1 20160413"
        .section    .note.GNU-stack,"",@progbits

1 个答案:

答案 0 :(得分:4)

是的,stmt1正在覆盖rax,但这不是问题。 stmt2然后edx = eax + 1使用lea以棘手的方式进行edxmovl %edx, (%rax)中的递增值将被写回(*ptr)++;的内存中。这意味着rax = ptr; /* load pointer */ eax = *rax; /* fetch current value */ edx = eax + 1; /* calculate new value */ rax = ptr; /* load pointer again */ *rax = edx; /* write new value */ 已分为多个步骤,如下所示:

addl $1,(%rax)

是的,可以使用void foo(int* ptr) { (*ptr)++; } 。您可能没有启用优化,这就是您看到低效代码的原因。

启用优化后,输入以下代码:

    addl    $1, (%rdi)
    ret

生成这个程序集:

void foo(int* ptr)
{
    *ptr = 42;
    (*ptr)++;
}

而且:

    movl    $43, (%rdi)
    ret

给出:

    private const int RECORDER_SAMPLERATE = 16000;
    private const ChannelIn RECORDER_CHANNELS = ChannelIn.Mono;
    private const Android.Media.Encoding RECORDER_AUDIO_ENCODING = Android.Media.Encoding.Pcm16bit;

   ...

    var bufferSize = AudioRecord.GetMinBufferSize(RECORDER_SAMPLERATE, RECORDER_CHANNELS, RECORDER_AUDIO_ENCODING);

    audioBuffer = new byte[bufferSize];
    audioRecord = new AudioRecord(
        // Hardware source of recording.
        AudioSource.Mic,
        // Frequency
        RECORDER_SAMPLERATE,
        // Mono or stereo
        RECORDER_CHANNELS,
        // Audio encoding
        RECORDER_AUDIO_ENCODING,
        // Length of the audio clip.
        audioBuffer.Length
    );

    audioRecord.StartRecording();

    ...

    using (var fileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write))
        {
            while (true)
            {
                if (endRecording)
                {
                    endRecording = false;
                    break;
                }
                try
                {
                    // Keep reading the buffer while there is audio input.
                    int numBytes = await audioRecord.ReadAsync(audioBuffer, 0, audioBuffer.Length);
                    await fileStream.WriteAsync(audioBuffer, 0, numBytes);
                    // Do something with the audio input.
                }
                catch (Exception ex)
                {
                    Console.Out.WriteLine(ex.Message);
                    break;
                }
            }
            fileStream.Close();
        }
        audioRecord.Stop();
        audioRecord.Release();