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

QQ登录

只需一步,快速开始

搜索
热搜: 下载 VB C 实现 编写
查看: 6080|回复: 5

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

[复制链接]
发表于 2015-12-12 01:39:15 | 显示全部楼层 |阅读模式

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

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

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

  2. flp_start

  3. ;设置卷标
  4. flp_add_empty_file "FLPBUILD",A_VolLabel

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

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

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

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

现在放上flpbuild.inc的内容——
  1. ;FLP文件构建器
  2. ;作者:0xAA55
  3. ;网站:http://www.0xaa55.com
  4. ;请保留原作者信息。

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

  15. %macro fn8_3 1
  16. %%SFN db %1
  17. times 11-($-%%SFN) db " "
  18. %endmacro

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

  21. ;文件属性位
  22. %define A_Normal        0x00
  23. %define A_ReadOnly        0x01
  24. %define A_Hidden        0x02
  25. %define A_System        0x04
  26. %define A_VolLabel        0x08
  27. %define A_LFNItem        0x0F
  28. %define A_Directory        0x10
  29. %define A_Archive        0x20

  30. ;宏名:flp_set_create_time
  31. ;描述:设置文件创建的日期和时间
  32. ;参数:
  33. ;MakeTime(时间)
  34. ;MakeDate(日期)
  35. %macro flp_set_create_time 2
  36.         %define _flp_cdate %1
  37.         %define _flp_ctime %2
  38. %endmacro

  39. ;宏名:flp_set_last_write_time
  40. ;描述:设置文件创建的日期和时间
  41. ;参数:
  42. ;MakeTime(时间)
  43. ;MakeDate(日期)
  44. %macro flp_set_last_write_time 2
  45.         %define _flp_wdate %1
  46.         %define _flp_wtime %2
  47. %endmacro

  48. ;宏名:flp_write_cluster_number
  49. ;描述:在FAT表写入簇号
  50. %macro flp_write_cluster_number 1
  51.         %assign cur_clus_num (%1)&0xfff
  52.         %if curclus & 1
  53.                 segment fat1
  54.                 db last_clus_num & 0xff
  55.                 db ((last_clus_num>>8) & 0xf) | ((cur_clus_num & 0xf)<<4)
  56.                 db cur_clus_num >> 4
  57.                 segment fat2
  58.                 db last_clus_num & 0xff
  59.                 db ((last_clus_num>>8) & 0xf) | ((cur_clus_num & 0xf)<<4)
  60.                 db cur_clus_num >> 4
  61.         %endif
  62.         %assign curclus curclus+1
  63.         %assign last_clus_num cur_clus_num
  64. %endmacro

  65. ;宏名:flp_write_cluster_end
  66. ;描述:在FAT表簇链中写入末簇
  67. %macro flp_write_cluster_end 0
  68.         flp_write_cluster_number 0xfff
  69. %endmacro

  70. ;宏名:flp_write_seq_clus
  71. ;描述:在FAT表簇链中写入有序的簇号
  72. ;参数:
  73. ;簇数
  74. %macro flp_write_seq_clus 1
  75.         %if %1>1
  76.                 %rep %1-1
  77.                         flp_write_cluster_number curclus+1
  78.                 %endrep
  79.         %endif
  80.         flp_write_cluster_end
  81. %endmacro

  82. ;宏名:flp_start
  83. ;描述:开始构建FLP文件
  84. %macro flp_start 0
  85.         segment dbr
  86.         incbin"dbr.bin"
  87.         segment fat1
  88.         segment fat2
  89.         segment root
  90.         segment data
  91.        
  92.         flp_set_create_time     MakeDate(2015,12,11),MakeTime(23,0,0)
  93.         flp_set_last_write_time MakeDate(2015,12,11),MakeTime(23,0,0)
  94.        
  95.         %assign curclus 0
  96.         flp_write_cluster_number 0xff0
  97.         flp_write_cluster_number 0xfff
  98. %endmacro

  99. ;宏名:flp_add_empty_file
  100. ;描述:添加空文件到根目录区
  101. ;参数:
  102. ;短文件名
  103. ;文件属性
  104. %macro flp_add_empty_file 2
  105.         segment root
  106.         fn8_3 %1
  107.         db %2
  108.         db 0
  109.         db 0
  110.         dw _flp_ctime
  111.         dw _flp_cdate
  112.         dw _flp_wdate
  113.         dw 0
  114.         dw _flp_wtime
  115.         dw _flp_wdate
  116.         dw 0
  117.         dd 0
  118. %endmacro

  119. ;宏名:flp_add_file
  120. ;描述:添加文件到根目录区
  121. ;参数:
  122. ;文件名
  123. ;短文件名
  124. ;文件属性
  125. %macro flp_add_file 3
  126.         ;先将文件添加到数据区
  127.         segment data
  128.         %%SOF:
  129.         incbin %1
  130.         %%EOF:
  131.         %%LOF equ %%EOF-%%SOF
  132.         %if %%LOF
  133.                 %%StartClus equ (%%SOF-$$)/512+2
  134.                 %%NbClus equ (%%LOF-1)/512+1
  135.                 times 512*%%NbClus-%%LOF db 0
  136.         %else
  137.                 %%StartClus equ 0
  138.                 %%NbClus equ 0
  139.         %endif

  140.         ;然后在根目录添加目录项
  141.         segment root
  142.         fn8_3 %2
  143.         db %3
  144.         db 0
  145.         db 0;文件创建时间的十毫秒数
  146.         dw _flp_ctime
  147.         dw _flp_cdate
  148.         dw _flp_wdate
  149.         dw %%StartClus>>16
  150.         dw _flp_wtime
  151.         dw _flp_wdate
  152.         dw %%StartClus
  153.         dd %%LOF
  154.        
  155.         ;之后更新FAT表
  156.         flp_write_seq_clus %%NbClus
  157. %endmacro

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

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

参考资料:
http://www.0xaa55.com/thread-5-1-1.html

类似的例子:使用汇编构造一个ico图标文件或cur光标文件
http://www.0xaa55.com/thread-1204-1-1.html
回复

使用道具 举报

发表于 2016-3-8 22:53:19 | 显示全部楼层
VERY GOOD  !
回复 赞! 靠!

使用道具 举报

发表于 2017-5-19 01:03:49 | 显示全部楼层
最近装了个OS却发现VMTool不支持,费了很大的劲儿才写了个软盘镜像,最后才把一些东西从VM里边取出来。
结果发现自己白写了,因为A5这边有现成的。但是我也把我的发上来。

  1. ; FDDBOOT.IMG
  2. ; 05142017
  3. DB 0xEB, 0xFE, 0x90 ; Disassemble code. As an infinite loop.
  4. DB "ABCDEFGH"       ; OEM Identifier. For 8 Bytes.
  5. DW 512              ; Number of each sector. (Must be 512 bytes for FAT12.)
  6. DB 1                ; Number of each cluster. (Which must equal to one sector.)
  7. DW 1                ; Boot record sector offset. (Usually start with the 1st sector.)
  8. DB 2                ; Number of File Allocation tables. (Must be 2 for FAT12.)
  9. DW 224              ; Number of root directories.
  10. DW 2880             ; Size of the disk. (Must be 2880 sectors for FAT12.)
  11. DB 0xF0             ; Media type. (Must be 0xF0 for FAT12.)
  12. DW 9                ; Length of FAT. (Must be 9 sectors for FAT12.)
  13. DW 18               ; How many sectors are there in a track. (Must be 18 for FAT12.)
  14. DW 2                ; Number of disk heads. (Wich must be 2.)
  15. DD 0                ; No hidden sectors. No extra partitions.
  16. DD 2880             ; Disk size again.
  17. DB 0x00             ; 0x00 for a floppy disk. 0x80 for a hard disk.
  18. DB 0x00             ; Reserved. For WinNT use only.
  19. DB 0x29             ; Signature (Must be 0x28 or 0x29.)
  20. DD 0xFFFFFFFF       ; Volume ID.
  21. DB "ABCDEFGHIJ "    ; Disk name. (11 bytes padding with spaces.)
  22. DB "FAT12   "       ; Disk format type. (8 bytes. Padding with spaces.)
  23. RESB 448            ; Boot code.
  24. DB 0x55, 0xAA       ; 0xAA55 signature.
  25. RESB 1474048        ; Reserve byte with 0x00.
  26. ; End. 26 lines totally. Please compile with NASM assembler. nasm -o fddboot.img FDDBOOT.ASM
复制代码
回复 赞! 靠!

使用道具 举报

发表于 2017-11-6 07:51:42 | 显示全部楼层
够屌,汇编果然
回复 赞! 靠!

使用道具 举报

发表于 2018-5-3 20:37:04 | 显示全部楼层
如果做一个VDI或者VMDK镜像,方法大致也是如此??
回复 赞! 靠!

使用道具 举报

 楼主| 发表于 2018-5-5 02:03:08 | 显示全部楼层
誓不回头 发表于 2018-5-3 20:37
如果做一个VDI或者VMDK镜像,方法大致也是如此??

不一样的。
回复 赞! 靠!

使用道具 举报

本版积分规则

QQ|Archiver|小黑屋|技术宅的结界 ( 滇ICP备16008837号 )|网站地图

GMT+8, 2024-11-24 10:15 , Processed in 0.042984 second(s), 30 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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