技术宅的结界

 找回密码
 立即注册→加入我们

QQ登录

只需一步,快速开始

搜索
热搜: 下载 VB C 实现 编写
查看: 2276|回复: 5
收起左侧

【汇编】用nasm构造一个软盘镜像

[复制链接]

1041

主题

2327

帖子

5万

积分

用户组: 管理员

一只技术宅

UID
1
精华
217
威望
288 点
宅币
18059 个
贡献
36587 次
宅之契约
0 份
在线时间
1731 小时
注册时间
2014-1-26
发表于 2015-12-12 01:39:15 | 显示全部楼层 |阅读模式

欢迎访问技术宅的结界,请注册或者登录吧。

您需要 登录 才可以下载或查看,没有帐号?立即注册→加入我们

x
之前我生成软盘镜像用的是UltraISO,使用它来将一个个文件拷进一个3.5英寸软盘镜像里,就像下图这样。。
20151212021423.png
偶尔我也通过使用VMware虚拟机生成一个空的软盘镜像,然后用虚拟机Windows将其格式化并往里面添加文件。。
这两种方法都……是手动的。我不喜欢这样。然而我也懒得直接用C或者VB写一个自动的制造软盘镜像的东西。我想用一个更加方便的方式来完成。。
于是我就写了一个汇编的inc文件,用nasm编译一个汇编的“脚本”来生成一个软盘镜像(虽然这似乎更麻烦了)
你只需要包含我的inc然后像这样写代码,就可以生成一个有文件的软盘镜像了!
[Asm] 纯文本查看 复制代码
%include"flpbuild.inc"

flp_start

;设置卷标
flp_add_empty_file "FLPBUILD",A_VolLabel

;添加文件
flp_add_file "build.bat",	"BUILD   BAT",A_Normal|A_ReadOnly
flp_add_file "picture.jpg",	"PICTURE JPG",A_Normal
flp_add_file "flpbuild.inc","FLPBUILDINC",A_Normal
flp_add_file "flp.asm",		"FLP     ASM",A_Normal

flp_end
(虽然文件不能一个一个地添加,而且也不能添加子文件夹,不过这好歹是可以自动化的)
用这种方法“编译”出来的img文件可以用UltraISO正常打开、查看里面的文件。
20151212025905.png
软盘使用的是FAT12文件系统,对于这个文件系统,它有个DBR引导扇区,2个FAT表,1个根目录表,和数据区。如何才能让汇编器分别往这几个不同的地方都添加自己想要添加的东西呢?用“段”来实现。

通常情况下我们编写汇编语言程序的时候,都会定义.text段(即代码段)、.data段(数据段)等。不同的段被用于存储不同类型的数据,这些段单独存在,不会被拆开存储。因此我们可以巧妙利用这一特性,通过分段来让汇编器把我们生成的字节丢到不同的位置,最后再把这些段拼接起来,形成一个完整的文件。

然后我们用编译DOS的.COM后缀的程序的方法,让nasm“编译”我们的软盘就行了。生成的文件是.COM程序那样的平坦结构模型,因此所有的段都是直接连在一起的。这正好符合我们的需求——将软盘镜像的DBR扇区、FAT表、根目录、数据区等连接在一起。

现在放上flpbuild.inc的内容——
[Asm] 纯文本查看 复制代码
;FLP文件构建器
;作者:0xAA55
;网站:http://www.0xaa55.com
;请保留原作者信息。

;用法:
;1、建立新的汇编文件
;2、包含这个头文件
;3、使用flp_start宏,进行初始化操作
;4、使用flp_add_file宏来添加文件,参数详见宏定义。
;   或者使用flp_add_empty_file来添加空白文件。
;   你可以重复使用上面的宏来添加多个文件。
;   补充:添加文件之前,你还可以调用flp_set_create_time来设置文件的创建时间,或
;   flp_set_last_write_time来设置文件的最后写入时间。
;5、最后,调用flp_end结束(会填充0来完成整个镜像文件的构造)

%macro fn8_3 1
%%SFN db %1
times 11-($-%%SFN) db " "
%endmacro

%define MakeTime(h,m,s) (((s>>1)&0x1f)|((m&0x3f)<<5)|((h&0x1f)<<11))
%define MakeDate(y,m,d) ((d&0x1f)|((m&0xf)<<5)|(((y-1980)&0x7f)<<9))

;文件属性位
%define A_Normal	0x00
%define A_ReadOnly	0x01
%define A_Hidden	0x02
%define A_System	0x04
%define A_VolLabel	0x08
%define A_LFNItem	0x0F
%define A_Directory	0x10
%define A_Archive	0x20

;宏名:flp_set_create_time
;描述:设置文件创建的日期和时间
;参数:
;MakeTime(时间)
;MakeDate(日期)
%macro flp_set_create_time 2
	%define _flp_cdate %1
	%define _flp_ctime %2
%endmacro

;宏名:flp_set_last_write_time
;描述:设置文件创建的日期和时间
;参数:
;MakeTime(时间)
;MakeDate(日期)
%macro flp_set_last_write_time 2
	%define _flp_wdate %1
	%define _flp_wtime %2
%endmacro

;宏名:flp_write_cluster_number
;描述:在FAT表写入簇号
%macro flp_write_cluster_number 1
	%assign cur_clus_num (%1)&0xfff
	%if curclus & 1
		segment fat1
		db last_clus_num & 0xff
		db ((last_clus_num>>8) & 0xf) | ((cur_clus_num & 0xf)<<4)
		db cur_clus_num >> 4
		segment fat2
		db last_clus_num & 0xff
		db ((last_clus_num>>8) & 0xf) | ((cur_clus_num & 0xf)<<4)
		db cur_clus_num >> 4
	%endif
	%assign curclus curclus+1
	%assign last_clus_num cur_clus_num
%endmacro

;宏名:flp_write_cluster_end
;描述:在FAT表簇链中写入末簇
%macro flp_write_cluster_end 0
	flp_write_cluster_number 0xfff
%endmacro

;宏名:flp_write_seq_clus
;描述:在FAT表簇链中写入有序的簇号
;参数:
;簇数
%macro flp_write_seq_clus 1
	%if %1>1
		%rep %1-1
			flp_write_cluster_number curclus+1
		%endrep
	%endif
	flp_write_cluster_end
%endmacro

;宏名:flp_start
;描述:开始构建FLP文件
%macro flp_start 0
	segment dbr
	incbin"dbr.bin"
	segment fat1
	segment fat2
	segment root
	segment data
	
	flp_set_create_time     MakeDate(2015,12,11),MakeTime(23,0,0)
	flp_set_last_write_time MakeDate(2015,12,11),MakeTime(23,0,0)
	
	%assign curclus 0
	flp_write_cluster_number 0xff0
	flp_write_cluster_number 0xfff
%endmacro

;宏名:flp_add_empty_file
;描述:添加空文件到根目录区
;参数:
;短文件名
;文件属性
%macro flp_add_empty_file 2
	segment root
	fn8_3 %1
	db %2
	db 0
	db 0
	dw _flp_ctime
	dw _flp_cdate
	dw _flp_wdate
	dw 0
	dw _flp_wtime
	dw _flp_wdate
	dw 0
	dd 0
%endmacro

;宏名:flp_add_file
;描述:添加文件到根目录区
;参数:
;文件名
;短文件名
;文件属性
%macro flp_add_file 3
	;先将文件添加到数据区
	segment data
	%%SOF:
	incbin %1
	%%EOF:
	%%LOF equ %%EOF-%%SOF
	%if %%LOF
		%%StartClus equ (%%SOF-$$)/512+2
		%%NbClus equ (%%LOF-1)/512+1
		times 512*%%NbClus-%%LOF db 0
	%else
		%%StartClus equ 0
		%%NbClus equ 0
	%endif

	;然后在根目录添加目录项
	segment root
	fn8_3 %2
	db %3
	db 0
	db 0;文件创建时间的十毫秒数
	dw _flp_ctime
	dw _flp_cdate
	dw _flp_wdate
	dw %%StartClus>>16
	dw _flp_wtime
	dw _flp_wdate
	dw %%StartClus
	dd %%LOF
	
	;之后更新FAT表
	flp_write_seq_clus %%NbClus
%endmacro

;宏名:flp_end
;描述:结束FLP文件的构建,做收尾工作
%macro flp_end 0
	%if curclus & 1
		flp_write_cluster_end
	%endif
	segment fat1
	times 9*512-($-$$) db 0
	segment fat2
	times 9*512-($-$$) db 0
	segment root
	times 14*512-($-$$) db 0
	segment data
	times 2847*512-($-$$) db 0
%endmacro
通过使用这些宏,我们就可以生成一个软盘镜像文件了。
用flp_add_empty_file来添加空文件,然后用flp_add_file来添加文件。
但是就目前而言,这东西不能添加文件夹,不能往文件夹里添加文件,并且不支持长文件名。不过我们可以在现在用的这些宏的基础之上,添加一些新的宏,比如,写一个新的宏使其在添加文件的时候,将目录项添加到别的地方而不是root段(这个“别的地方”就是我们的子文件夹的内容了)并修改flp_end来将子文件夹放在数据区的最后(同时还要保证FAT表也同步)。。当然还有更好的办法只是我还没想出来而已。现在先这么用吧。等到需要的时候——我们还是干脆用C语言写个生成软盘镜像的东西吧。

flpbuild.7z (99.15 KB, 下载次数: 2, 售价: 1 个宅币)

1

主题

4

帖子

27

积分

用户组: 初·技术宅

UID
1497
精华
0
威望
1 点
宅币
21 个
贡献
0 次
宅之契约
0 份
在线时间
2 小时
注册时间
2016-2-20
发表于 2016-3-8 22:53:19 | 显示全部楼层
VERY GOOD  !

85

主题

263

帖子

3649

积分

用户组: 管理员

No. 418

UID
418
精华
13
威望
52 点
宅币
1969 个
贡献
1248 次
宅之契约
0 份
在线时间
252 小时
注册时间
2014-8-9
发表于 2017-5-19 01:03:49 | 显示全部楼层
最近装了个OS却发现VMTool不支持,费了很大的劲儿才写了个软盘镜像,最后才把一些东西从VM里边取出来。
结果发现自己白写了,因为A5这边有现成的。但是我也把我的发上来。
[Asm] 纯文本查看 复制代码
; FDDBOOT.IMG
; 05142017
DB 0xEB, 0xFE, 0x90 ; Disassemble code. As an infinite loop.
DB "ABCDEFGH"       ; OEM Identifier. For 8 Bytes.
DW 512              ; Number of each sector. (Must be 512 bytes for FAT12.)
DB 1                ; Number of each cluster. (Which must equal to one sector.)
DW 1                ; Boot record sector offset. (Usually start with the 1st sector.)
DB 2                ; Number of File Allocation tables. (Must be 2 for FAT12.)
DW 224              ; Number of root directories.
DW 2880             ; Size of the disk. (Must be 2880 sectors for FAT12.)
DB 0xF0             ; Media type. (Must be 0xF0 for FAT12.)
DW 9                ; Length of FAT. (Must be 9 sectors for FAT12.)
DW 18               ; How many sectors are there in a track. (Must be 18 for FAT12.)
DW 2                ; Number of disk heads. (Wich must be 2.)
DD 0                ; No hidden sectors. No extra partitions.
DD 2880             ; Disk size again.
DB 0x00             ; 0x00 for a floppy disk. 0x80 for a hard disk.
DB 0x00             ; Reserved. For WinNT use only.
DB 0x29             ; Signature (Must be 0x28 or 0x29.)
DD 0xFFFFFFFF       ; Volume ID.
DB "ABCDEFGHIJ "    ; Disk name. (11 bytes padding with spaces.)
DB "FAT12   "       ; Disk format type. (8 bytes. Padding with spaces.)
RESB 448            ; Boot code.
DB 0x55, 0xAA       ; 0xAA55 signature.
RESB 1474048        ; Reserve byte with 0x00.
; End. 26 lines totally. Please compile with NASM assembler. nasm -o fddboot.img FDDBOOT.ASM
In the beginning I was not the best.
And the world was also not the best.
But I still know that I am who I am.
Because I think that it is good.
I have been working hard.
I have been keeping growth with the world.
And it was so.

1

主题

85

帖子

91

积分

用户组: 小·技术宅

UID
3026
精华
0
威望
1 点
宅币
3 个
贡献
0 次
宅之契约
0 份
在线时间
6 小时
注册时间
2017-10-31
发表于 2017-11-6 07:51:42 | 显示全部楼层
够屌,汇编果然

0

主题

25

帖子

52

积分

用户组: 小·技术宅

UID
1741
精华
0
威望
2 点
宅币
23 个
贡献
0 次
宅之契约
0 份
在线时间
4 小时
注册时间
2016-6-3
发表于 2018-5-3 20:37:04 | 显示全部楼层
如果做一个VDI或者VMDK镜像,方法大致也是如此??

1041

主题

2327

帖子

5万

积分

用户组: 管理员

一只技术宅

UID
1
精华
217
威望
288 点
宅币
18059 个
贡献
36587 次
宅之契约
0 份
在线时间
1731 小时
注册时间
2014-1-26
 楼主| 发表于 2018-5-5 02:03:08 | 显示全部楼层
誓不回头 发表于 2018-5-3 20:37
如果做一个VDI或者VMDK镜像,方法大致也是如此??

不一样的。

本版积分规则

QQ|申请友链||Archiver|手机版|小黑屋|技术宅的结界 ( 滇ICP备16008837号|网站地图

GMT+8, 2019-8-19 07:44 , Processed in 0.125442 second(s), 40 queries , Gzip On.

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表