flat assembler
Message board for the users of flat assembler.

Index > Macroinstructions > macro to generate hdd image

Thread Post new topic Reply to topic

Joined: 12 Apr 2005
Posts: 501
Location: Belarus
zhak 08 Mar 2015, 22:25
Hi guys,
To learn fasm macros, I decided to write one to generate a hdd image. But I'm not sure if I'm doing it the right way.

Below is what I got so far. It reserves space for partitions of a given size and adds records to partition table. It's also possible to add mbr bootcode from a binary file.
if ~ defined struct
  include '%include%/macro/struct.inc'
end if



struct mbr_partition_record_entry
  boot_indicator  rb 1
  start_head      rb 1
  start_sector    rb 1
  start_cylinder  rb 1
  partition_type  rb 1
  end_head        rb 1
  end_sector      rb 1
  end_cylinder    rb 1
  start_lba       rd 1
  size            rd 1

macro image type, bootcode, signature {
  if `type eq 'mbr'
    local ..start
    ..start = $
    if ~ bootcode eq
      file bootcode
    end if
    times MBR_BOOTCODE_SIZE - ($ - ..start) db 0
    if ~ signature eq
      dd signature
      dd 0
    end if
    dw 0
    partition_record: times 4 * sizeof.mbr_partition_record_entry db 0
    display 'ERROR: invalid image type: '#`type
  end if

macro partition index, boot_indicator, type, start_lba, size {
  sz = sizeof.mbr_partition_record_entry
  store byte boot_indicator at\
    partition_record + index * sz + mbr_partition_record_entry.boot_indicator
  store byte (start_lba / SECTORS_PER_TRACK) mod HEADS_PER_CYLINDER at\
    partition_record + index * sz + mbr_partition_record_entry.start_head
  ssec = (start_lba mod SECTORS_PER_TRACK) + 1
  store word ((scyl and 0xff) shl 8) or (scyl shr 2 and 0xc0) or (ssec and 0x3f) at\
    partition_record + index * sz + mbr_partition_record_entry.start_sector
  store byte type at\
    partition_record + index * sz + mbr_partition_record_entry.partition_type
  store byte ((start_lba + size) / SECTORS_PER_TRACK) mod HEADS_PER_CYLINDER at\
    partition_record + index * sz + mbr_partition_record_entry.end_head
  ecyl = (start_lba + size) / (HEADS_PER_CYLINDER * SECTORS_PER_TRACK)
  esec = ((start_lba + size) mod SECTORS_PER_TRACK) + 1
  store word ((ecyl and 0xff) shl 8) or (ecyl shr 2 and 0xc0) or (esec and 0x3f) at\
    partition_record + index * sz + mbr_partition_record_entry.end_sector
  store dword start_lba at\
    partition_record + index * sz + mbr_partition_record_entry.start_lba
  store dword size at\
    partition_record + index * sz + mbr_partition_record_entry.size
  times BYTES_PER_SECTOR * start_lba - ($ - $$) db 0
  times BYTES_PER_SECTOR * size db 0

macro endi {}
image mbr
  partition 0, 0x80, 0x0c, 63, 1

What interests me is:
1. I fill partition table by using store directive. This is the only way I found for now. Probably there's a more elegant solution?
2. To add values to proper partition table entries I added index parameter to partition macro. Maybe there's a way to achieve the same result without using additional index param?
2. In STRUCT.INC from fasm macros, I saw the following:
field@struct equ name    

But what is that @ symbol? What is it for?
3. Not sure right now what could be put in endi macro to finalize the structure. Completely lost in struct.inc source %)
Thanks in advance for your assistance.
Post 08 Mar 2015, 22:25
View user's profile Send private message Reply with quote

Joined: 23 Oct 2009
Posts: 881
l_inc 09 Mar 2015, 00:51
Your code has quite a number of problems:
1) There's no way to check if a macro is already defined. The if directive is an assembly time directive. Hence the first line checks if there's no assembly time variable/constant or label named "struct" that can be used at this particular source code location. The condition is true, no matter if "struct.inc" was included before or not.

2) As for the second line of code:
....a) It is a bad idea to explicitly expand the include variable. It may contain multiple paths and it's expanded implicitly anyway. The correct include string is include "macro/struct.inc" .
....b) As long as if is an assembly time directive, it is not able to prevent processing of the preprocessor directive include. Hence "struct.inc" will be included no matter if the condition is true or false.

As for the rest some things are suboptimal but generally look OK.

Regarding you questions:
1. The struct macro defines a macro and a struc named as the name passed to the struct macro. Both take a list of the arguments composed of the fields of the struct. Thus much better would be to fill the partition table by invoking the automatically created mbr_partition_record_entry macro at its definition location. This would require you to redesign the macros a bit.

2. If you properly redesign the macros (as suggested before), the index will no longer be needed by design in a natural way.

2. (Yes, the second second point Smile) The @ symbol is for nothing. It has no special meaning for the assembler, but it's a naming convention for globally accessible symbols in some official macros. It literally means "[a symbolic constant called] field at struct [related macros / header file]". I generally consider using this naming convention to be worse than generating unique names with the local directive. However you need to enclose your macros into a single macroblock to be able to share such a generated name across them. Look here for an example.

3. If you properly redesign the macros (as suggested before), you'll naturally see what you need to put there. It is however additionally advisable to define the partition macro inside the image macro and to purge it inside the endi macro. This way you'll be able to restrict the use of the partition macro to the scope of the image description.

As for the "struct.inc" I think it's too complicated for learning basics from it.

Faith is a superposition of knowledge and fallacy
Post 09 Mar 2015, 00:51
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  

< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum

Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.