【发布时间】: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