macos - 从 MSVC 裸函数转换总线错误 : Inline x86 assembly with GCC asm{} block on Mac OS X,

标签 macos assembly gcc clang inline-assembly

当我尝试在 Snow Leopard 上运行使用 gcc 4.2.1 编译的代码时,出现“总线错误”

#include <stdio.h>

/*__declspec(naked)*/ void
doStuff(unsigned long int val, unsigned long int flags, unsigned char *result)
{
    __asm{
        push eax
        push ebx
       push ecx
        push edx
    
        mov eax, dword ptr[esp + 24]//val
        mov ebx, dword ptr[esp + 28]//flags
        //mov ecx, dword ptr[esp + 32]//result

        and eax, ebx
        mov result, eax

        pop edx
        pop ecx
        pop ebx
        pop eax

        ret
    }
}

int main(int argc, char *argv[])
{
    unsigned long val = 0xAA00A1F2; 
    unsigned long flags = 0x00100001;   
    unsigned char result = 0x0;
    
    doStuff(val, flags, &result);   
    printf("Result is: %2Xh\n", result);
    
    return 0;
}

我正在使用以下命令来编译 gcc -fasm-blocks -m32 -o so so.c没有任何错误或警告。我正在尝试在 doStuff() 函数中运行一些汇编指令并将答案分配给结果。我做错了什么?

(这台 Mac 上的 gcc 命令实际上可能是 clang,或者是 Apple 的修改,因为主线 GCC 不支持 -fasm-blocks 。)

注意:这在 Windows 上的 Visual Studio 中运行良好,但我必须注释掉 declspec(naked) 才能让 gcc 在 Mac 上编译它。

最佳答案

您收到总线错误的原因是您在汇编代码中调用retret 使程序控制转移到堆栈顶部的返回地址,您可以通过使用 pushpop 来操作该地址。我强烈建议您在英特尔指令集引用中查找 ret 的作用。

下面是我在运行 Mac OS X 10.6.7 的 iMac 上编译并成功运行的代码。

#include <stdio.h>

/*__declspec(naked)*/ void
doStuff(unsigned long int val, unsigned long int flags, unsigned char *result)
{
  __asm
    {
        push eax
        push ebx
        push ecx

        mov eax, dword ptr[ebp + 8]  //val
        mov ebx, dword ptr[ebp + 12] //flags
        mov ecx, dword ptr[ebp + 16] //result

        and eax, ebx
        mov [ecx], eax

        pop ecx
        pop ebx
        pop eax
      }
}

int main(int argc, char *argv[])
{
  unsigned long val =   0xAA00A1F2;
  unsigned long flags = 0x00100002;
  unsigned char result = 0x0;
    
  doStuff(val, flags, &result);
  printf("Result is: %2Xh\n", result);
    
  return 0;
}

显着的变化是:

  1. 删除内联程序集中的 ret
  2. 使用寄存器ebp而不是esp来引用doStuff的参数
  3. flags更改为0x00100002

更改 (1) 修复了总线错误,(2) 使参数引用更加一致,(3) 只是确保函数按预期工作的快速方法。

最后,如果您还没有熟悉 GNU 调试器 GDB,我强烈建议您熟悉一下。您可以在项目页面http://www.gnu.org/software/gdb/找到更多信息。以及有关 Mac 实现和教程的信息,请访问 https://developer.apple.com/library/archive/documentation/DeveloperTools/gdb/gdb/gdb_toc.html .

关于macos - 从 MSVC 裸函数转换总线错误 : Inline x86 assembly with GCC asm{} block on Mac OS X,,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5784824/

相关文章:

windows - RTL(波斯语-阿拉伯语)字母在 android studio 编辑器中搞砸了

assembly - 计算 JMP 操作码

c++ - 如何使用 gcc 原子内置函数?

iphone - 应用程序在 Apple LLVM 3.0 上崩溃但在 LLVM GCC 4.2 上运行正常

iphone - 使用 NEON 优化 RGBA8888 到 RGB565 的转换

gcc undefined reference

Java 代码在处理器速度较慢的 Mac 上运行速度比在 Windows 计算机上运行速度更快?

macos - 使用 NSView 进行图层支持绘图时不会调用 drawRect

c++ - macOS上的wxWidgets暗模式

windows - PE文件中没有.BSS