将汇编 NASM 代码链接到 GCC

2023-12-30

我在编译汇编代码(nasm)时遇到问题。

在 Linux (elf32) 上,使用 g++ 编译后它不会失败,但是当我尝试使用 i686-w64-mingw32-g++ (对于 Win32)构建它时,它失败了。

我的 build.sh 脚本:

#!/bin/bash

nasm -fwin32 wct.asm
i686-w64-mingw32-g++ -m32 -O2 -Wall -fno-exceptions -ffloat-store -ffast-math -fno-rounding-math -fno-signaling-nans -fcx-limited-range -fno-math-errno -funsafe-math-optimizations -fassociative-math -freciprocal-math -ffinite-math-only -fno-signed-zeros -fno-trapping-math -frounding-math -fsingle-precision-constant -fcx-fortran-rules -fno-rtti -mfpmath=387 -mfancy-math-387 -fno-ident -fmerge-all-constants -mpreferred-stack-boundary=2 -falign-functions=1 -falign-jumps=1 -falign-loops=1 -fno-unroll-loops -fno-math-errno -s main.cpp wct.obj -o wct.exe
strip --strip-unneeded wct.exe

有汇编代码:

   [bits 32]
   section .text
   global wct

   wct:

    mov esi, [esp+4]
    mov edi, esi
    mov ecx, [esp+8]

    @L:
            lodsw
            sub ax, 04141h

            cmp al,0Fh
            jne @F
            dec al
            jmp @E
            @F:
            cmp al,0Eh
            jne @E
            inc al
            @E:

            mov bx, ax
            shr bx, 8

            cmp bl,0Fh
            jne @@F
            dec bl
            jmp @@E
            @@F:
            cmp bl,0Eh
            jne @@E
            inc bl
            @@E:

            shl al, 4
            add ax, bx
            stosb
    loop @L
    ret

主要.cpp:

#include <fstream>

using namespace std;

extern "C" int wct(char* buff, int N);

#define N 1024*1024

char buff[N];
ifstream in;
ofstream out;
int size;

int main(int argc, char* argv[]) {

    if ( argc == 1 ) return 0;

    in.open(argv[1], ios_base::in | ios_base::binary);

    if ( argc >= 3 )
        out.open(argv[2], ios_base::out | ios_base::binary);

    if( in.is_open())
    {
        while(!in.eof())
        {
            in.read((char *)&buff, sizeof buff);
            size = in.gcount()/2;
            wct((char *)&buff, size);

            if ( out.is_open())
                out.write((char *)&buff, size);
            else
            {
                out.close();
            }
        }
    }

    in.close();
    out.close();

    return 0;
}

我显然做错了什么,因为我在使用 build.sh 脚本时总是遇到相同的错误:

/tmp/cc3SD7dA.o:main.cpp:(.text.startup+0x90): undefined reference to `wct'
collect2: error: ld returned 1 exit status

我该如何解决这个问题?


在 Windows 上,GCC 编译器期望外部符号中有一个前导下划线。所以改变一切wct在asm文件中_wct.

如果你想在 Windows 和 Linux 中测试程序,你可以“全球化”两个连续的标签:wct and _wct:

...
global wct
global _wct
...
wct:
_wct:
...

Linux 获得wct没有下划线,Windows 也会随之而来。

顺便说一句:汇编过程是一个 C 函数,必须遵循CDECL 调用约定 https://en.wikipedia.org/wiki/X86_calling_conventions#cdecl。该函数可以自由改变寄存器EAX, ECX, and EDX(呼叫者已保存)。其他寄存器(EBX,ESI,EDI,EBP) 必须原封不动地返回。如果函数需要使用它们,它必须保存并恢复它们(被调用者保存):

wct:
_wct:

 push esi                ; sp+= 4
 push edi                ; sp+= 4
 push ebx                ; sp+= 4
                        ; ======
                        ; sp+= 12
 mov esi, [esp+16]
 mov edi, esi
 mov ecx, [esp+20]

 ...

 pop ebx
 pop edi
 pop esi
 ret
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

将汇编 NASM 代码链接到 GCC 的相关文章

随机推荐

  • 如何在 Android Studio Java 中将数组上传到 Firestore 数据

    我想上传这样的数据 编辑过的问题 I have ArrayList
  • 如何消除真正非递归函数在 JIT_TailCall 中花费的时间

    我正在编写一个 64 位 F 解决方案 分析显示出令人惊讶且意想不到的大量时间花费在JIT TailCall 它实际上在运行时占据主导地位 大约 80 它与它的邪恶表弟一起出现JIT TailCallHelperStub ReturnAdd
  • 如何设置RadioGroup中只有一个RadioButton可以同时选中

    我在radiogroup中创建了一个单选按钮 但是当我尝试运行应用程序时 所有单选按钮都可以一直被选择 如何设置一次只能选择一个单选按钮 我在用着Fragment RadioGroup radioGroup RadioGroup rootV
  • 跳转到 Intellij IDEA 中的编辑器快捷方式

    I can use F12 to jump to project tree if it was the last tool that I used but is there a shortcut for jumping back to ed
  • 将CAB文件添加到操作系统设计中

    我需要将 CAB 文件 我的安装 添加到操作系统设计中 但我找不到方法来做到这一点 我需要它来在操作系统第一次加载时自动安装程序 我说的是win Compact 7 你能帮助我吗 我有点困惑 为什么要将 CAB 添加到操作系统设计中并在运行
  • 如何在 Java 中比较两个版本字符串?

    是否有比较版本号的标准习惯用法 我不能只使用直接的 String CompareTo 因为我还不知道最大的点释放数量是多少 我需要比较版本并确保以下内容成立 1 0 lt 1 1 1 0 1 lt 1 1 1 9 lt 1 10 这篇旧文章
  • 在 Ruby on Rails (MySQL) 中使用“end”作为列名称

    我有一个带有 结束 列 日期时间格式 的模型 却发现每当我尝试在查询中引用该列时 Heroku 都会崩溃并因不合逻辑的 Active Record 错误而烧毁 我花了两个小时尝试调试这个极其简单的查询 之后我将该列重命名为 end at 所
  • Git 存储库从一台机器到另一台机器

    所以我有一个 git 存储库 我曾在某个时刻提取过该存储库 并且该存储库驻留在服务器上 我无权访问我从中提取它的原始存储库 如何将代码从现有服务器获取到另一台计算机 编辑1 所以它看起来像这样 计算机 A 我最初从中签出的 git 存储库
  • pandas 0.21.0 时间戳与 matplotlib 的兼容性问题

    我刚刚将 pandas 从 0 17 1 更新到 0 21 0 以利用一些新功能 并遇到了与 matplotlib 的兼容性问题 我也将其更新到最新的 2 1 0 特别是 Timestamp 对象似乎发生了重大变化 我碰巧有另一台机器仍在运
  • Python 编译器是否可以优化一些整数运算?

    灵感来自this https stackoverflow com questions 11476190 why 0 6 is 6 false关于Python缓存小整数的问题 Python编译器是否可以在编译时将 0 6 替换为 6 下面的代
  • android TabLayout 从服务器设置图标

    我可以从服务器上设置图标吗TabLayout using Picasso library private string path 192 168 0 102 project a png TabLayout tabLayout TabLayo
  • 在 Heroku 上使用 React、Axios 访问内部 API

    我正在构建一个全栈 React 应用程序 该应用程序使用 Axios 访问其自己的后端 API 在我的本地环境中 以下内容按预期工作 服务器使用 JSON 数据进行响应 然后正确呈现该数据 axios get api questions c
  • Grunt Livereload + Grunt Connect 代理

    我在我的 API 中使用 Rails 在前面使用 AngularJS 并且在使 livereload grunt connect 代理正常工作时遇到一些问题 这是我的 gruntfile 中的片段 connect options port
  • MYSQL 查询锁定服务器

    当尝试执行此查询时 我的 mysql 服务器 cpu 使用率达到 100 并且页面停止运行 我在 Client Code Date Time Time Stamp Activity Code Employee Name ID Transac
  • 为什么我看到“排序规则‘xxx’对于字符集‘yyy’无效”

    我使用的是 Amazon RDS 上的 MySQL 5 6 22 InnoDB 我尝试将所有表 列 连接和数据库字符集和排序规则设置设置为 utf8mb4 utf8mb4 unicode ci 我在任何地方都找不到任何证据表明任何东西都有字
  • Java获取html文件

    复制 如何用 Java 以编程方式下载网页 https stackoverflow com questions 238547 how do you programmatically download a webpage in java 如何
  • 如何将 IPython 笔记本转换为 PDF 和 HTML?

    我想转换我的 ipython 笔记本来打印它们 或者只是以 html 格式发送它们 我注意到已经有一个工具可以做到这一点 NB转换 https github com ipython nbconvert 虽然我已经下载了它 但我不知道如何使用
  • 在 Firebase 托管上提供 gzip 压缩文件

    我对使用 Firebase 托管提供 gzipped html css js 文件感兴趣 我尝试在 firebase json 中设置 Content Encoding 标头 但在部署时出错 据称 您可以设置的唯一标头包括 Cache Co
  • 为什么我要 std::move std::shared_ptr?

    我一直在寻找铿锵源码 https clang llvm org doxygen CompilerInstance 8cpp source html l00069我发现了这个片段 void CompilerInstance setInvoca
  • 将汇编 NASM 代码链接到 GCC

    我在编译汇编代码 nasm 时遇到问题 在 Linux elf32 上 使用 g 编译后它不会失败 但是当我尝试使用 i686 w64 mingw32 g 对于 Win32 构建它时 它失败了 我的 build sh 脚本 bin bash