【问题标题】:How to split single asm with multiple segments into multiple files with single segment?如何将具有多个段的单个 asm 拆分为具有单个段的多个文件?
【发布时间】:2019-09-12 07:14:12
【问题描述】:

!!!已解决!!!:stackoverflow 上的后续问题:how can i get the dos exe build from segments in multiple asm files binary identical to the single asm file version

UPDATE 0:解决了外部问题,但我遇到了设置问题 数据段,请参阅 UPDATES

(也将此问题发布在:https://www.reddit.com/r/asm/comments/d33mpn/masm_x86_16bit_dos_exe_how_to_split_single_asm/

我正在开发一种工具,该工具有助于 DOS 16 位的二进制相同重组,IDA Pro asm 输出,为此我使用基于此 asm 代码的“定义明确”的输入 exe(它是我的几个难以逆转的功能的游乐场,强烈反对这个问题)

[all_in_one.asm]

.model medium
.386

seg000 segment use16
text db 'Hello World!',0ah,0dh,'$'
seg000 ends

seg001 segment use16
;assume cs:seg001 ; for TASM
start proc
  mov ax,seg seg000
  mov ds,ax
  push ax
  pop ax
  call print
  mov ax,4c00h
  int 21h
start endp

seg001 ends

seg002 segment use16
;assume cs:seg002 ; for TASM
print proc far
  mov dx,offset text
  mov ah,09h
  int 21h
  retf
print endp

seg002 ends

seg003 segment stack use16
  db 256 dup (?)
seg003 ends

end start

我没有故意使用 .STACK 或 MASM 的其他功能,因为 IDA 的正常反转结果充满了我想要 1:1 复制的特殊情况(多个堆栈、段排序等),我对如何编写不感兴趣MASM 中的相同较短,只是确切的结果与我相关

我可以使用构建上述代码

[build.cmd]

:: MASM x86, 14.16.27032.1 from VS2017 Community (current UASM, TASM also work)
ml.exe /c /omf all_in_one.asm
:: UniLink v1.11 [beta] (build 11.23), ftp://ftp.styx.cabel.net/pub/UniLink/
ulink.exe all_in_one.obj
:: Microsoft Linker 16bit, Version 5.60.339 Dec 5 1994
link.exe all_in_one.obj,,,,,

并使用两个链接器创建一个完全工作的 16 位 dos 可执行文件(使用 IDA 和 Dosbox 测试)(还应该使用 TLink、WLink、Optlink 和 Alink 以及所有其他支持 16 位 dos 可执行文件的可用链接器)

一切都很好……但是

反转的可执行文件往往有很大的段,有时有 20 个甚至超过 100 个,因此我的工具将这些段拆分为单个文件,如果不是所有内容都被抓住,更容易使单个段文件与原始文件二进制兼容在一起

所以我将文件拆分为段文件(以及用于前向声明的 inc 文件,也许 MASM 有更好的方法 - 前向声明的数据应尽可能是类型安全的,我已阅读有关 EXTERNDEF 和其他但我不知道使用它有什么优点/缺点)

[seg000.asm]

.model medium
.386

seg000 segment use16
  text db 'Hello World!',0ah,0dh,'$'
seg000 ends

end

[seg000.inc]

seg000 segment use16
  extern text:far
seg000 ends

[seg001.asm]

.model medium
.386

; forward declare segments
include seg000.inc
include seg002.inc

seg001 segment use16

start proc
  mov ax,seg seg000
  mov ds,ax
  push ax
  pop ax
  call print
  mov ax,4c00h
  int 21h
start endp

seg001 ends

end start

[seg002.asm]

.model medium
.386

; forward declare segments
include seg000.inc

seg002 segment use16

print proc far
  mov dx,offset text
  mov ah,09h
  int 21h
  retf
print endp

seg002 ends

end

[seg002.inc]

seg002 segment use16
  extrn print:far
seg002 ends

[seg003.asm]

.model medium
.386

seg003 segment stack use16
  db 256 dup (?)
seg003 ends

end

并尝试构建它

[build_multiple.cmd]

ml.exe /c /omf seg000.asm
ml.exe /c /omf seg001.asm
ml.exe /c /omf seg002.asm
ml.exe /c /omf seg003.asm
ulink.exe seg000.obj seg001.obj seg002.obj seg003.obj
link.exe seg000.obj seg001.obj seg002.obj seg003.obj,,,,,

所有 asm 文件都可以组装,但两个链接器都返回错误

UniLink v1.11 [beta] (build 11.23)
Error: Unresolved external 'text' referenced from 'seg001.obj'

Microsoft (R) Segmented Executable Linker  Version 5.60.339 Dec  5 1994
Copyright (C) Microsoft Corp 1984-1993.  All rights reserved.

seg002.obj(seg002.asm) : error L2029: 'text' : unresolved external
seg001.obj(seg001.asm) : error L2029: 'text' : unresolved external

我对分段内容的前向声明是否正确?知道如何解决未解决的外部链接器错误吗?

更新 1: 未解决的外部已通过公共修复

我将我的数据段更改为:

seg000 segment use16
  public text ; <====
  text db 'Hello World!',0ah,0dh,'$'
seg000 ends

现在它链接了,但我的堆栈段似乎不正确

UniLink v1.11 [beta] (build 11.23)
Error: SP value out of range
Error: SS value out of range

Microsoft Linker 不会打印任何错误,但生成的 exe 只会打印垃圾

更新 2:

all_in_one 和 splitted-segments exe 是二进制(带标题)除了一个字节之外是相同的

seg001 中的 mov ax,seg dseg 编码不同

[all_in_one exe]

B8 (00) 10 --> mov ax, 0x1000

[拆分的exe]

B8 (01) 10 --> mov ax, 0x1001

这意味着拆分的 exe 使用 seg001 作为数据段(我的第一个代码段)而不是 seg000,然后尝试从代码段打印一些内容,直到在 ram 中找到一个“$”

为什么会这样?

到目前为止我的想法是:

我在 seg001 的定义之前包括了这个 seg000.inc(字面意思是空段,仅用于转发和外部),可能是汇编程序认为包含的空段就在那里并且可以使用,并且因为它的大小0 与 seg001 相等的段?

如果这就是原因 - 那么我该如何转发我的 procs 和值呢?

【问题讨论】:

  • 快速(未选中):一个 .obj 文件中的 EXTERN 应与另一个 .obj 文件中的 PUBLIC 对应。
  • 如果您有新问题,请不要编辑现有问题以包含它,而是发布一个新问题。一旦您的问题得到回答,您就不能更改您的问题,以免现有答案无效。

标签: assembly x86 dos masm 16-bit


【解决方案1】:

第一个问题是通过在正确的位置设置PUBLIC来解决。

第二个问题是由.MODEL 指令和不完整的SEGMENT 声明引起的。

构建一个包含所有SEGMENT 声明并包含在所有.ASM 文件中的文件:

segments.inc:

seg000 segment para public use16 
seg000 ends

seg001 segment para public use16
seg001 ends

seg002 segment para public use16
seg002 ends

seg003 segment use16 stack
seg003 ends

其他文件如下所示:

seg000.asm:

.386
include segments.inc

public text

seg000 segment
  text db 'Hello World!',0ah,0dh,'$'
seg000 ends

end

seg001.asm:

.386
include segments.inc

extern print:FAR

seg001 segment

start proc
  mov ax, seg000
  mov ds,ax
  push ax
  pop ax
  call print
  mov ax,4c00h
  int 21h
start endp

seg001 ends

end start

seg002.asm:

.386
include segments.inc

extern text:BYTE

seg002 segment

print proc far
  mov dx,offset text
  mov ah,09h
  int 21h
  retf
print endp

seg002 ends

end

seg003.asm:

.386
include segments.inc

seg003 segment
  db 256 dup (?)
seg003 ends

end

我在 WinXP 中使用了 MASM32 packagebuild_multiple.cmd 中的 LINK16.EXE

@ECHO OFF

ml.exe /c /omf seg000.asm
ml.exe /c /omf seg001.asm
ml.exe /c /omf seg002.asm
ml.exe /c /omf seg003.asm

C:\masm32\bin\link16.exe /L seg000.obj seg001.obj seg002.obj seg003.obj;

查看.MAP 文件是否所有段的顺序都正确。

【讨论】:

  • 出于好奇:如果我在不同的段中有多个文本变量或具有相同名称的过程,这是否也有效?
  • 它可以工作,但 all_in_one.exe 是不同的,即使在 exe 标头中也是如此 - 我的主要目标是与组合版本(将来自 IDA)二进制兼容,我已经删除了 .模型并更正了 all_in_one.asm 中的段,但生成的 exe 中仍然发生变化,我将检查映射文件的段开始和大小
  • 我已经用地图信息更新了问题,小差异破坏了我在 all_in_one.exe 和 multi.exe 之间的二进制兼容性
  • 删除 .model medium 指令会导致 multi.exe 中的大量调用,在崩溃之后,我读到在 .386 强制使用之前使用 .mode16
  • @llm:如果删除类名('DATA'、'CODE'),您可以生成几乎相同的 .exe 文件。我已经相应地编辑了我的答案。多个 .exe 最后用零填充。我没有找到解决办法。我的解决方案适用于link16.exeulink.exe 似乎有错误。
猜你喜欢
  • 1970-01-01
  • 2011-08-10
  • 2017-02-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多