Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Need support for splitting an integer. #27

Open
j3pic opened this issue Dec 29, 2018 · 3 comments
Open

Need support for splitting an integer. #27

j3pic opened this issue Dec 29, 2018 · 3 comments

Comments

@j3pic
Copy link
Owner

j3pic commented Dec 29, 2018

Consider the EDID format used by HDMI monitors: https://en.wikipedia.org/wiki/Extended_Display_Identification_Data#EDID_1.4_data_format

Part of this spec calls for an integer whose lowest 8 bits are followed by the lowest 8 bits of an unrelated integer, followed by the highest 4 bits of the first integer, then the highest 4 bits of the second integer.

Something like this:

(defbinary troll-format (:byte-order :big-endian)
    (number-of-frobs 0 :type (unsigned-byte 8))
    (unrelated-cruft 0 :type (unsigned-byte 8))
    (rest-of-number-of-frobs 0 :type (unsigned-byte 4)) ;; u mad bro?
    (rest-of-unrelated-cruft 0 :type (unsigned-byte 4)))

I've seen other formats that do things like this (but never an explanation of why someone would do
this), so perhaps there should be some way to specify that REST-OF-NUMBER-OF-FROBS is part of NUMBER-OF-FROBS (and which part it is in that case, since someone could specify a format in which the chunks are laid out in middle-endian order).

@j3pic
Copy link
Owner Author

j3pic commented Dec 25, 2019

One approach that seems reasonably elegant is to have :before and :after options that could be used to sequence fragments relative to other named fragments of the same integer.

So the troll-format above could be written like this:

(defbinary troll-format (:byte-order :big-endian)
    (number-of-frobs 0 :type (unsigned-byte 8))
    (unrelated-cruft 0 :type (unsigned-byte 8))
    (rest-of-number-of-frobs 0 :type (unsigned-byte 4 :after number-of-frobs)) 
    (rest-of-unrelated-cruft 0 :type (unsigned-byte 4 :after unrelated-cruft))
    (middle-of-number-of-frobs 0 :type (unsigned-byte 8 :before rest-of-number-of-frobs))

The macro would detect the presence of :before and :after fragments and
generate code that shifts and masks each fragment into the right place upon reading/writing.

@j3pic
Copy link
Owner Author

j3pic commented Feb 4, 2020

I've found another real-world data format that splits integers across non-adjacent bytes. The x86 architecture's global descriptor table is described on page 38 here: https://www.cs.bham.ac.uk/~exr/lectures/opsys/10_11/lectures/os-dev.pdf

@j3pic
Copy link
Owner Author

j3pic commented Jul 19, 2021

Perhaps a more readable syntax would be to give the fragments numbers instead of :before and :after tags:

(defbinary troll-format (:byte-order :big-endian)
    (number-of-frobs 0 :type (unsigned-byte 8 :fragment 0))
    (unrelated-cruft 0 :type (unsigned-byte 8 :fragment 1))
    (rest-of-number-of-frobs 0 :type (unsigned-byte 4 :fragment-of (number-of-frobs 2)
    (rest-of-unrelated-cruft 0 :type (unsigned-byte 4 :fragment-of (unrelated-cruft 0)))
    (middle-of-number-of-frobs 0 :type (unsigned-byte 8 :fragment-of (number-of-frobs 1)))

The primary variable would have a :fragment in its type indicating which position it's in. The secondary variables
would use :fragment-of to specify both the primary variable to mask into, and the position relative to other variables.

This scheme would be inadequate if there was an array that interleaved fragments of its elements.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant