【问题标题】:ARM inline assembly code not working correctly at runtimeARM 内联汇编代码在运行时无法正常工作
【发布时间】:2014-01-14 13:55:57
【问题描述】:

此代码旨在打开 opensl_es 音频记录以单声道捕获流,复制流并分别处理左声道和右声道,然后将两个声道混合成输出流,稍后也使用 opensl_es 播放。汇编代码的原因是因为我在之前用 c 编写的混合函数中发现了一个瓶颈,这是一个简单的 for 循环将左右缓冲区连接到输出缓冲区

这个问题很奇怪,当我把我想要的日志放在输出流中时,左右缓冲区的混合工作,我在日志中看到它,当我尝试播放流时应用程序崩溃,每当我评论日志时都会发生同样的情况,由于某种原因,应用程序只是崩溃了,所以我开始认为它与我正在使用的寄存器或汇编代码中的某些东西有关,我是汇编新手,所以手臂组装有什么我遗漏的吗?

知道为什么会发生这种情况,或者我应该如何解决这个问题?

这里是代码:第一个函数是我用来捕获声音调用过程函数的主要函数。第二个“mux”是其中包含内联程序集的函数。

void start_playing()
{
    OPENSL_STREAM  *pStream;
    int samps, i, j;
    short  inbuffer[VECSAMPS_MONO], outbuffer[VECSAMPS_STEREO];
    pStream = android_OpenAudioDevice(SR,1,2,BUFFERFRAMES);
    if(pStream == NULL)
    {
        return;
    }

    on   = 1;
    iLog = 0;
    while (on)
    {
        samps = android_AudioInRaw(pStream,inbuffer,VECSAMPS_MONO); //audio recording
        //signal processing process called here for left channel then for right channel (equalizing, etc)
        mux(inbuffer, inbuffer, outbuffer,VECSAMPS_MONO); //Assembly mixing of left and right channel into output channel
        //android_AudioOutRaw(pStream,outbuffer,samps*2);//audio playing
    }

    android_CloseAudioDevice(pStream);
}


//assembly function here
void mux(short *pLeftBuf, short *pRightBuf, short *pOutBuf, int vecsamps_mono)
{
    int *pIter;
    *pIter = vecsamps_mono / 4;

    __android_log_print(ANDROID_LOG_INFO, "$$$$$$$$$$$$", "value : %d , %d , %d , %d",pLeftBuf[0],pLeftBuf[1], pRightBuf[0],pRightBuf[1]);

    asm volatile(
        "ldr r9, %[outbuf];"
        "ldr r0, %[leftbuf];"
        "ldr r1, %[rightbuf];"
        "ldr r2, %[iter];"
        "ldr r8, [r2];"

        "loop: "

        "ldr r2, [r0];"
        "ldr r3, [r1];"

        "ldr r7, =0xffff;"

        "and r4, r2, r7;"
        "and r5, r3, r7;"
        "lsl r5, r5, #16;"
        "orr r4, r4, r5;"

        "lsl r7, r7, #16;"

        "and r5, r2, r7;"
        "and r6, r3, r7;"
        "lsr r6, r6, #16;"
        "orr r5, r5, r6;"

        "str r4, [r9];"
        "str r5, [r9, #4];"

        "add r0, r0, #4;"
        "add r1, r1, #4;"
        "add r9, r9, #8;"

        "subs r8, r8, #1;"
        "bne loop"
                :[outbuf] "=m" (pOutBuf)
                :[leftbuf] "m" (pLeftBuf) ,[rightbuf] "m" (pRightBuf),[iter] "m" (pIter)
                :"r0","r1","r2","r3","r4","r5","r8","r9","memory","cc"
        );
    __android_log_print(ANDROID_LOG_INFO, "##################", "value : %d , %d , %d , %d" ,*pOutBuf,*(pOutBuf+1),*(pOutBuf+2) ,*(pOutBuf+3));
}

有什么建议吗? 这是我在 logcat 中遇到的错误:

01-14 11:41:40.992:A/libc(16161):致命信号 11 (SIGSEGV) 位于 0x00000000 (code=1),线程 16178 (Thread-4783)

【问题讨论】:

  • 你得到什么样的错误? (PS:停止使用这些可怕的 TAB。)
  • @meaning-matters 我用 logcat 中的错误更新了帖子
  • 您应该查看生成的目标文件。您可能会看到唯一生成的是第一个 ldr r9。问题是你正在使用';'在每个 asm 语句的末尾,它在汇编中开始一个注释,但不结束行本身,所以最后你会得到一个带有 loooooong 注释的指令。你必须以'\n'结束每一行。但除非你希望这是一个练习,否则你应该坚持使用他们的 C-Code。据我所知,一个体面的编译器应该能够轻松胜过您的代码。
  • 在谷歌上搜索stackoverflow SIGSEGV 0x00000000,看看结果是否有线索。你能用调试器单步调试这段代码,看看它发生在哪里吗?
  • @meaning-matters 我用谷歌搜索了这个错误,但我能找到的只是当你尝试通过空指针访问内存时它发生了,现在我相信这个指针变为空的原因是因为我的注册表操作或类似的东西,不,我无法使用调试器单步执行此代码,因为我无法使 ds-5 调试器与我的内联汇编代码一起工作,所以这就是我寻求帮助的原因,我错过了一些东西。

标签: c assembly android-ndk arm cpu-registers


【解决方案1】:
*pIter = vecsamps_mono / 4;
...
    "ldr r2, %[iter];"
    "ldr r8, [r2];"
...
     ...[iter] "m" (pIter)

也许,只是也许vecsamps_mono 不是有效内存地址的 4 倍。

在第一行取消引用一个未初始化的指针。

【讨论】:

  • 看起来也不需要是指针。最终,您只需要 R8 中的值 vecsamps_mono / 4,因此将其作为指针(在未初始化的取消引用之上)传递只是为了取消引用以获取其值,这似乎是多余的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-04
  • 2010-12-07
  • 1970-01-01
相关资源
最近更新 更多