c - 如何让 Watcom C 编译器(wcc)和 WASM 生成相同的 8086 机器码?

标签 c assembly x86 watcom

对于此 C 源代码:

int add(int a, int b) { return a + b; }

,用于 8086 的 Watcom C 编译器 (wcc -s -ms -os -0 prog.c) 生成以下机器码(十六进制):01 D0 C3 , 反汇编为add ax, dx (01 D0) + ret (C3).

对于这个程序集源代码:

PUBLIC  add_
EXTRN   _small_code_:BYTE
_TEXT SEGMENT BYTE PUBLIC USE16 'CODE'
add_: add ax, dx
      ret
_TEXT ENDS
END

,Watcom 汇编程序(WASM,wasm -ms -0 prog.wasm)生成以下机器码(十六进制):03 C2 C3,反汇编为添加 ax, dx (03 C2) + ret (C3).

因此,它们生成相同的 8086 汇编指令的不同二进制编码 add ax, dx

仅供引用,如果我在 Watcom C 内联汇编中实现该函数,那么机器代码输出将与 WASM 相同。

不同指令编码的集合:

  • 添加 ax, dx。 wcc: 01 D0; wasm:03 C2
  • mov bx, ax。 wcc: 89 C3; wasm:8B D8
  • 添加 ax,字节 9。 wcc: 05 09 00; wasm:83 C0 09

如何让 Watcom C 编译器(用于 C 代码)和 WASM 生成具有相同二进制编码的指令?是否有命令行标志或其他一些配置选项?我找不到任何内容。

我需要它的原因是我想通过仅编写 WASM 源来重现一个用 Watcom C 编写的可执行程序文件,并且我希望最终输出与原始输出完全相同。

最佳答案

这个答案的灵感来自@RaymondChen 的评论。

这里有一个繁琐的多步骤方法来更改 wcc 发出的机器代码以匹配 wasm 的输出:

  1. 照常将 C 源代码 witm wcc(OpenWatcom 的一部分)编译为 .obj 文件。

  2. 使用dmpobj(OpenWatcom 的一部分)提取_TEXT 段的机器代码字节。

  3. 使用 ndisasm(NASM 的一部分,ndisasm -b 16 file.obj)反汇编机器代码字节。

  4. 编写并运行自定义源文本过滤器以仅保留汇编指令并将其转换为 WASM 语法。

  5. 使用 wasm(OpenWatcom 的一部分)生成第二个 .obj 文件。

  6. 使用 dmpobj 提取第二个 .obj 文件的 _TEXT 段的机器码字节。

  7. 编写并运行一个自定义二进制过滤器,用从第二个 .obj 文件中提取的等效字节替换第一个 .obj 文件的 _TEXT 段中的机器代码字节,使用dmpobj 调用输出中的偏移量。

这些步骤避免使用 wdis -a(从 .obj 到程序集源的转换),因为这是有损的(它不包括 .obj 文件中的所有内容),这可能会产生不需要的更改,以后会引起问题。

关于c - 如何让 Watcom C 编译器(wcc)和 WASM 生成相同的 8086 机器码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74209302/

相关文章:

c++ - Typedef-name 与 C++ 中的 struct 标记冲突

我可以将 Intel 语法的 x86 程序集与 GCC 一起使用吗?

c - 如何获取栈指针的值? (MIPS 海湾合作委员会)

assembly - 为什么我必须检查有符号操作的溢出标志而不是 8086 中的进位标志?

c++ - 节能自旋环

assembly - QEMU 是否使用与 x86 到 x86 仿真的 guest 寄存器相同的主机寄存器?

c - 如何在 C 中调用函数打印 2D const char* 数组?

c - 初始化数组中结构体中的变量

c - 使用邻接表进行深度优先搜索

c - 为什么 GCC 会为几乎相同的 C 代码生成如此截然不同的程序集?