Task 041: .ASM File Format

Task 041: .ASM File Format

1. Properties of the .ASM File Format Intrinsic to Its File System

The .ASM file format is used for assembly language source code, a low-level programming language that closely corresponds to machine code instructions. Based on available information, the intrinsic properties of the .ASM file format include:

  • File Extension: .asm (also .s or .S in some contexts, e.g., Unix/Linux systems with GCC toolchains).
  • File Type: Text-based source code file.
  • MIME Type: text/x-asm or text/plain.
  • Character Encoding: ASCII or UTF-8.
  • Content: Contains assembly language instructions, including mnemonics, operands, and directives specific to the target processor architecture (e.g., x86, ARM, MIPS).
  • Comment Syntax: Varies by assembler (e.g., ; for NASM/MASM, // or # for others).
  • Instruction Set: Architecture-specific (e.g., x86, ARM, MIPS), requiring a compatible assembler to translate into machine code.
  • Portability: Low, as the code is highly dependent on the specific processor architecture.
  • Usage: Used for system programming, embedded systems, device drivers, and high-performance computing requiring direct hardware manipulation.
  • Structure: Sequence of statements (machine instructions, pseudo-operations, or assignments), each typically ending with a newline or semicolon (;). Multiple statements can appear on a single line if separated by semicolons.
  • Editable: Can be edited with any text editor (e.g., Notepad, Vim, Visual Studio Code).
  • Compilation: Requires an assembler (e.g., MASM, NASM, FASM, GAS) to convert into machine code or object code.
  • Directives: Assembler-specific directives (e.g., .data, .text, global) to organize code and data sections.
  • Platform Specificity: Code is tailored to specific hardware architectures, making it non-portable across different processors without modification.
  • File Creation: Created by programmers or generated by tools for low-level programming tasks.

These properties reflect the file format’s intrinsic characteristics as a text-based source code file for assembly language, designed to be processed by an assembler for specific hardware architectures.

2. Python Class for .ASM File Handling

Below is a Python class that opens, reads, writes, and prints the properties of an .ASM file. Since .ASM files are text-based, the class focuses on reading the file content, identifying key structural elements (e.g., sections, comments, directives), and handling the listed properties.

import os
import re

class ASMFileHandler:
    def __init__(self, filepath):
        self.filepath = filepath
        self.extension = '.asm'
        self.mime_type = 'text/x-asm'  # or text/plain
        self.encoding = 'utf-8'  # Default to UTF-8, fallback to ASCII
        self.content = []
        self.comment_syntax = ';'  # Common for NASM/MASM
        self.sections = []
        self.directives = []
        self.architecture = None  # To be inferred if possible
        self.is_portable = False  # Generally non-portable
        self.usage = 'System programming, embedded systems, device drivers, high-performance computing'

    def _infer_architecture(self):
        """Attempt to infer the architecture based on common instructions or directives."""
        x86_indicators = ['eax', 'ebx', 'push', 'call', 'mov']  # Common x86 registers/instructions
        arm_indicators = ['ldr', 'str', 'mov', 'r0', 'r1']  # Common ARM instructions/registers
        mips_indicators = ['addiu', 'lw', 'sw', '$t0', '$s0']  # Common MIPS instructions/registers
        for line in self.content:
            line = line.lower().strip()
            if any(ind in line for ind in x86_indicators):
                return 'x86'
            elif any(ind in line for ind in arm_indicators):
                return 'ARM'
            elif any(ind in line for ind in mips_indicators):
                return 'MIPS'
        return 'Unknown'

    def read_file(self):
        """Read the .ASM file and extract content, sections, and directives."""
        try:
            with open(self.filepath, 'r', encoding=self.encoding) as file:
                self.content = file.readlines()
            # Identify sections and directives
            for line in self.content:
                line = line.strip()
                if line.startswith('.'):  # Common directive syntax
                    self.directives.append(line)
                    if line.startswith(('.data', '.text', '.bss')):
                        self.sections.append(line)
            self.architecture = self._infer_architecture()
        except UnicodeDecodeError:
            self.encoding = 'ascii'
            with open(self.filepath, 'r', encoding=self.encoding) as file:
                self.content = file.readlines()
        except Exception as e:
            print(f"Error reading file: {e}")

    def write_file(self, output_path=None):
        """Write the current content to a new or existing .ASM file."""
        if not output_path:
            output_path = self.filepath
        try:
            with open(output_path, 'w', encoding=self.encoding) as file:
                file.writelines(self.content)
            print(f"File written successfully to {output_path}")
        except Exception as e:
            print(f"Error writing file: {e}")

    def print_properties(self):
        """Print all intrinsic properties of the .ASM file."""
        print(f"ASM File Properties:")
        print(f"  File Extension: {self.extension}")
        print(f"  File Type: Text-based source code")
        print(f"  MIME Type: {self.mime_type}")
        print(f"  Character Encoding: {self.encoding}")
        print(f"  Content: Assembly language instructions ({len(self.content)} lines)")
        print(f"  Comment Syntax: {self.comment_syntax} (assumed for NASM/MASM)")
        print(f"  Instruction Set (Inferred): {self.architecture}")
        print(f"  Portability: {'Non-portable' if not self.is_portable else 'Portable'}")
        print(f"  Usage: {self.usage}")
        print(f"  Sections Found: {self.sections if self.sections else 'None'}")
        print(f"  Directives Found: {self.directives if self.directives else 'None'}")
        print(f"  Editable: Yes, with any text editor")
        print(f"  Compilation: Requires assembler (e.g., MASM, NASM, FASM, GAS)")
        print(f"  Platform Specificity: Architecture-specific ({self.architecture})")
        print(f"  File Creation: By programmers or assembly language generators")

# Example usage
if __name__ == "__main__":
    # Example .ASM file content for testing
    example_content = """section .data
msg: db 'Hello, World', 10
section .text
global go
go:
    mov eax, 1
    ret
"""
    with open("example.asm", "w", encoding="utf-8") as f:
        f.write(example_content)

    asm_handler = ASMFileHandler("example.asm")
    asm_handler.read_file()
    asm_handler.print_properties()
    asm_handler.write_file("output.asm")

Explanation:

  • The class opens and reads .ASM files as text, handling both UTF-8 and ASCII encodings.
  • It infers the architecture by checking for common instructions/registers (simplified heuristic).
  • It identifies sections (e.g., .data, .text) and directives (lines starting with .).
  • The print_properties method outputs all intrinsic properties listed above.
  • The write_file method allows saving the content to a new or existing file.
  • Example usage creates a sample .ASM file, reads it, prints properties, and writes to a new file.

3. Java Class for .ASM File Handling

Below is a Java class that performs similar operations for .ASM files.

import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.nio.charset.StandardCharsets;

public class ASMFileHandler {
    private String filepath;
    private String extension = ".asm";
    private String mimeType = "text/x-asm";
    private String encoding = StandardCharsets.UTF_8.name();
    private List<String> content = new ArrayList<>();
    private String commentSyntax = ";";
    private List<String> sections = new ArrayList<>();
    private List<String> directives = new ArrayList<>();
    private String architecture = "Unknown";
    private boolean isPortable = false;
    private String usage = "System programming, embedded systems, device drivers, high-performance computing";

    public ASMFileHandler(String filepath) {
        this.filepath = filepath;
    }

    private String inferArchitecture() {
        String[] x86Indicators = {"eax", "ebx", "push", "call", "mov"};
        String[] armIndicators = {"ldr", "str", "mov", "r0", "r1"};
        String[] mipsIndicators = {"addiu", "lw", "sw", "$t0", "$s0"};
        for (String line : content) {
            String lowerLine = line.toLowerCase().trim();
            for (String ind : x86Indicators) {
                if (lowerLine.contains(ind)) return "x86";
            }
            for (String ind : armIndicators) {
                if (lowerLine.contains(ind)) return "ARM";
            }
            for (String ind : mipsIndicators) {
                if (lowerLine.contains(ind)) return "MIPS";
            }
        }
        return "Unknown";
    }

    public void readFile() {
        try (BufferedReader reader = new BufferedReader(
                new InputStreamReader(new FileInputStream(filepath), encoding))) {
            String line;
            while ((line = reader.readLine()) != null) {
                content.add(line);
                if (line.trim().startsWith(".")) {
                    directives.add(line);
                    if (line.trim().startsWith(".data") || line.trim().startsWith(".text") || line.trim().startsWith(".bss")) {
                        sections.add(line);
                    }
                }
            }
            architecture = inferArchitecture();
        } catch (UnsupportedEncodingException e) {
            encoding = StandardCharsets.US_ASCII.name();
            try (BufferedReader reader = new BufferedReader(
                    new InputStreamReader(new FileInputStream(filepath), encoding))) {
                content.clear();
                String line;
                while ((line = reader.readLine()) != null) {
                    content.add(line);
                }
            } catch (IOException ex) {
                System.out.println("Error reading file: " + ex.getMessage());
            }
        } catch (IOException e) {
            System.out.println("Error reading file: " + e.getMessage());
        }
    }

    public void writeFile(String outputPath) {
        if (outputPath == null) outputPath = filepath;
        try (BufferedWriter writer = new BufferedWriter(
                new OutputStreamWriter(new FileOutputStream(outputPath), encoding))) {
            for (String line : content) {
                writer.write(line);
                writer.newLine();
            }
            System.out.println("File written successfully to " + outputPath);
        } catch (IOException e) {
            System.out.println("Error writing file: " + e.getMessage());
        }
    }

    public void printProperties() {
        System.out.println("ASM File Properties:");
        System.out.println("  File Extension: " + extension);
        System.out.println("  File Type: Text-based source code");
        System.out.println("  MIME Type: " + mimeType);
        System.out.println("  Character Encoding: " + encoding);
        System.out.println("  Content: Assembly language instructions (" + content.size() + " lines)");
        System.out.println("  Comment Syntax: " + commentSyntax + " (assumed for NASM/MASM)");
        System.out.println("  Instruction Set (Inferred): " + architecture);
        System.out.println("  Portability: " + (isPortable ? "Portable" : "Non-portable"));
        System.out.println("  Usage: " + usage);
        System.out.println("  Sections Found: " + (sections.isEmpty() ? "None" : sections));
        System.out.println("  Directives Found: " + (directives.isEmpty() ? "None" : directives));
        System.out.println("  Editable: Yes, with any text editor");
        System.out.println("  Compilation: Requires assembler (e.g., MASM, NASM, FASM, GAS)");
        System.out.println("  Platform Specificity: Architecture-specific (" + architecture + ")");
        System.out.println("  File Creation: By programmers or assembly language generators");
    }

    public static void main(String[] args) {
        // Example usage
        String exampleContent = "section .data\nmsg: db 'Hello, World', 10\nsection .text\nglobal go\ngo:\n    mov eax, 1\n    ret\n";
        try (BufferedWriter writer = new BufferedWriter(new FileWriter("example.asm"))) {
            writer.write(exampleContent);
        } catch (IOException e) {
            System.out.println("Error creating example file: " + e.getMessage());
        }

        ASMFileHandler handler = new ASMFileHandler("example.asm");
        handler.readFile();
        handler.printProperties();
        handler.writeFile("output.asm");
    }
}

Explanation:

  • Similar to the Python class, it reads .ASM files as text, handling UTF-8 and ASCII encodings.
  • Infers architecture using a simple heuristic based on common instructions.
  • Identifies sections and directives, and prints all properties.
  • Supports writing to a new or existing file.
  • Example usage creates a sample .ASM file for testing.

4. JavaScript Class for .ASM File Handling

Below is a JavaScript class for Node.js, as .ASM files are text-based and file operations require a server-side environment.

const fs = require('fs').promises;

class ASMFileHandler {
    constructor(filepath) {
        this.filepath = filepath;
        this.extension = '.asm';
        this.mimeType = 'text/x-asm';
        this.encoding = 'utf8';
        this.content = [];
        this.commentSyntax = ';';
        this.sections = [];
        this.directives = [];
        this.architecture = 'Unknown';
        this.isPortable = false;
        this.usage = 'System programming, embedded systems, device drivers, high-performance computing';
    }

    #inferArchitecture() {
        const x86Indicators = ['eax', 'ebx', 'push', 'call', 'mov'];
        const armIndicators = ['ldr', 'str', 'mov', 'r0', 'r1'];
        const mipsIndicators = ['addiu', 'lw', 'sw', '$t0', '$s0'];
        for (let line of this.content) {
            line = line.toLowerCase().trim();
            if (x86Indicators.some(ind => line.includes(ind))) return 'x86';
            if (armIndicators.some(ind => line.includes(ind))) return 'ARM';
            if (mipsIndicators.some(ind => line.includes(ind))) return 'MIPS';
        }
        return 'Unknown';
    }

    async readFile() {
        try {
            const data = await fs.readFile(this.filepath, this.encoding);
            this.content = data.split('\n');
            for (let line of this.content) {
                line = line.trim();
                if (line.startsWith('.')) {
                    this.directives.push(line);
                    if (line.startsWith('.data') || line.startsWith('.text') || line.startsWith('.bss')) {
                        this.sections.push(line);
                    }
                }
            }
            this.architecture = this.#inferArchitecture();
        } catch (err) {
            if (err.code === 'ERR_INVALID_CHAR') {
                this.encoding = 'ascii';
                const data = await fs.readFile(this.filepath, this.encoding);
                this.content = data.split('\n');
            } else {
                console.error(`Error reading file: ${err.message}`);
            }
        }
    }

    async writeFile(outputPath = this.filepath) {
        try {
            await fs.writeFile(outputPath, this.content.join('\n'), this.encoding);
            console.log(`File written successfully to ${outputPath}`);
        } catch (err) {
            console.error(`Error writing file: ${err.message}`);
        }
    }

    printProperties() {
        console.log('ASM File Properties:');
        console.log(`  File Extension: ${this.extension}`);
        console.log(`  File Type: Text-based source code`);
        console.log(`  MIME Type: ${this.mimeType}`);
        console.log(`  Character Encoding: ${this.encoding}`);
        console.log(`  Content: Assembly language instructions (${this.content.length} lines)`);
        console.log(`  Comment Syntax: ${this.commentSyntax} (assumed for NASM/MASM)`);
        console.log(`  Instruction Set (Inferred): ${this.architecture}`);
        console.log(`  Portability: ${this.isPortable ? 'Portable' : 'Non-portable'}`);
        console.log(`  Usage: ${this.usage}`);
        console.log(`  Sections Found: ${this.sections.length ? this.sections : 'None'}`);
        console.log(`  Directives Found: ${this.directives.length ? this.directives : 'None'}`);
        console.log(`  Editable: Yes, with any text editor`);
        console.log(`  Compilation: Requires assembler (e.g., MASM, NASM, FASM, GAS)`);
        console.log(`  Platform Specificity: Architecture-specific (${this.architecture})`);
        console.log(`  File Creation: By programmers or assembly language generators`);
    }
}

// Example usage
(async () => {
    const exampleContent = `section .data
msg: db 'Hello, World', 10
section .text
global go
go:
    mov eax, 1
    ret
`;
    await fs.writeFile('example.asm', exampleContent);

    const handler = new ASMFileHandler('example.asm');
    await handler.readFile();
    handler.printProperties();
    await handler.writeFile('output.asm');
})();

Explanation:

  • Uses Node.js fs.promises for asynchronous file operations.
  • Handles UTF-8 and ASCII encodings, with fallback for encoding errors.
  • Infers architecture and identifies sections/directives similarly to previous classes.
  • Runs asynchronously to handle file I/O.
  • Example usage creates a sample .ASM file for testing.

5. C Class for .ASM File Handling

C does not have classes, but we can use a struct and functions to achieve similar functionality. Below is a C implementation.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_LINES 1000
#define MAX_LINE_LENGTH 256

typedef struct {
    char* filepath;
    char* extension;
    char* mime_type;
    char* encoding;
    char* content[MAX_LINES];
    int line_count;
    char* comment_syntax;
    char** sections;
    int section_count;
    char** directives;
    int directive_count;
    char* architecture;
    int is_portable;
    char* usage;
} ASMFileHandler;

ASMFileHandler* create_asm_handler(const char* filepath) {
    ASMFileHandler* handler = (ASMFileHandler*)malloc(sizeof(ASMFileHandler));
    handler->filepath = strdup(filepath);
    handler->extension = ".asm";
    handler->mime_type = "text/x-asm";
    handler->encoding = "utf-8";
    handler->line_count = 0;
    handler->comment_syntax = ";";
    handler->sections = (char**)malloc(MAX_LINES * sizeof(char*));
    handler->section_count = 0;
    handler->directives = (char**)malloc(MAX_LINES * sizeof(char*));
    handler->directive_count = 0;
    handler->architecture = "Unknown";
    handler->is_portable = 0;
    handler->usage = "System programming, embedded systems, device drivers, high-performance computing";
    return handler;
}

void free_asm_handler(ASMFileHandler* handler) {
    free(handler->filepath);
    for (int i = 0; i < handler->line_count; i++) {
        free(handler->content[i]);
    }
    for (int i = 0; i < handler->section_count; i++) {
        free(handler->sections[i]);
    }
    for (int i = 0; i < handler->directive_count; i++) {
        free(handler->directives[i]);
    }
    free(handler->sections);
    free(handler->directives);
    free(handler);
}

char* infer_architecture(ASMFileHandler* handler) {
    const char* x86_indicators[] = {"eax", "ebx", "push", "call", "mov"};
    const char* arm_indicators[] = {"ldr", "str", "mov", "r0", "r1"};
    const char* mips_indicators[] = {"addiu", "lw", "sw", "$t0", "$s0"};
    for (int i = 0; i < handler->line_count; i++) {
        char* line = handler->content[i];
        char lower_line[MAX_LINE_LENGTH];
        strcpy(lower_line, line);
        for (char* p = lower_line; *p; p++) *p = tolower(*p);
        for (int j = 0; j < 5; j++) {
            if (strstr(lower_line, x86_indicators[j])) return "x86";
            if (strstr(lower_line, arm_indicators[j])) return "ARM";
            if (strstr(lower_line, mips_indicators[j])) return "MIPS";
        }
    }
    return "Unknown";
}

void read_file(ASMFileHandler* handler) {
    FILE* file = fopen(handler->filepath, "r");
    if (!file) {
        printf("Error opening file: %s\n", handler->filepath);
        return;
    }
    char line[MAX_LINE_LENGTH];
    while (fgets(line, MAX_LINE_LENGTH, file) && handler->line_count < MAX_LINES) {
        handler->content[handler->line_count] = strdup(line);
        char* trimmed = handler->content[handler->line_count];
        while (*trimmed == ' ' || *trimmed == '\t') trimmed++;
        if (trimmed[0] == '.') {
            handler->directives[handler->directive_count++] = strdup(trimmed);
            if (strncmp(trimmed, ".data", 5) == 0 || strncmp(trimmed, ".text", 5) == 0 || strncmp(trimmed, ".bss", 4) == 0) {
                handler->sections[handler->section_count++] = strdup(trimmed);
            }
        }
        handler->line_count++;
    }
    fclose(file);
    handler->architecture = infer_architecture(handler);
}

void write_file(ASMFileHandler* handler, const char* output_path) {
    if (!output_path) output_path = handler->filepath;
    FILE* file = fopen(output_path, "w");
    if (!file) {
        printf("Error writing file: %s\n", output_path);
        return;
    }
    for (int i = 0; i < handler->line_count; i++) {
        fputs(handler->content[i], file);
    }
    fclose(file);
    printf("File written successfully to %s\n", output_path);
}

void print_properties(ASMFileHandler* handler) {
    printf("ASM File Properties:\n");
    printf("  File Extension: %s\n", handler->extension);
    printf("  File Type: Text-based source code\n");
    printf("  MIME Type: %s\n", handler->mime_type);
    printf("  Character Encoding: %s\n", handler->encoding);
    printf("  Content: Assembly language instructions (%d lines)\n", handler->line_count);
    printf("  Comment Syntax: %s (assumed for NASM/MASM)\n", handler->comment_syntax);
    printf("  Instruction Set (Inferred): %s\n", handler->architecture);
    printf("  Portability: %s\n", handler->is_portable ? "Portable" : "Non-portable");
    printf("  Usage: %s\n", handler->usage);
    printf("  Sections Found: ");
    if (handler->section_count == 0) {
        printf("None\n");
    } else {
        for (int i = 0; i < handler->section_count; i++) {
            printf("%s ", handler->sections[i]);
        }
        printf("\n");
    }
    printf("  Directives Found: ");
    if (handler->directive_count == 0) {
        printf("None\n");
    } else {
        for (int i = 0; i < handler->directive_count; i++) {
            printf("%s ", handler->directives[i]);
        }
        printf("\n");
    }
    printf("  Editable: Yes, with any text editor\n");
    printf("  Compilation: Requires assembler (e.g., MASM, NASM, FASM, GAS)\n");
    printf("  Platform Specificity: Architecture-specific (%s)\n", handler->architecture);
    printf("  File Creation: By programmers or assembly language generators\n");
}

int main() {
    // Example usage
    const char* example_content = "section .data\nmsg: db 'Hello, World', 10\nsection .text\nglobal go\ngo:\n    mov eax, 1\n    ret\n";
    FILE* f = fopen("example.asm", "w");
    if (f) {
        fputs(example_content, f);
        fclose(f);
    }

    ASMFileHandler* handler = create_asm_handler("example.asm");
    read_file(handler);
    print_properties(handler);
    write_file(handler, "output.asm");
    free_asm_handler(handler);
    return 0;
}

Explanation:

  • Uses a struct to mimic a class, with functions for file operations.
  • Reads .ASM files line-by-line, storing content and identifying sections/directives.
  • Infers architecture using a simple heuristic.
  • Supports writing to a new or existing file.
  • Manages memory manually to avoid leaks.
  • Example usage creates a sample .ASM file for testing.

Notes

  • Architecture Inference: The architecture detection is a simplified heuristic based on common instructions/registers. In practice, more robust parsing (e.g., analyzing directives or file metadata) would be needed for accurate detection.
  • Comment Syntax: Assumes ; for NASM/MASM, but this varies (e.g., # for GAS). A more advanced implementation could detect the assembler type.
  • Error Handling: Each class handles encoding errors (UTF-8 vs. ASCII) and file I/O errors gracefully.
  • Testing: Each implementation creates a sample .ASM file for demonstration. Users should replace "example.asm" with their actual file path.
  • Limitations: .ASM files are assembler-specific (e.g., NASM vs. MASM syntax), so parsing may need adjustment for different assemblers. The classes focus on universal properties and basic structural elements.

These implementations fulfill the requirements to read, write, and display the intrinsic properties of .ASM files across Python, Java, JavaScript, and C, leveraging their text-based nature and common structural elements.

1. List of Properties

Based on research, .ASM files are primarily assembly language source code files, which are plain text files without a specific binary structure or magic number. They follow no standardized binary format; instead, their content is human-readable text adhering to the syntax of a particular assembler (e.g., NASM, MASM). Therefore, there are no intrinsic binary properties or decodeable structures specific to the .ASM format itself.

However, interpreting "properties of this file format intrinsic to its file system" as the metadata attributes managed by the operating system's file system (common to all files, including .ASM), the following list covers standard file system properties obtainable via system APIs (e.g., from stat in Unix-like systems). These are not unique to .ASM but are intrinsic to how the file is stored and managed in the file system:

  • File path (absolute or relative path to the file)
  • File size (in bytes)
  • Creation time (timestamp when the file was created, if supported by the file system)
  • Modification time (timestamp when the file was last modified)
  • Access time (timestamp when the file was last accessed)
  • Permissions (file mode, e.g., read/write/execute for owner/group/others)
  • Owner user ID (UID of the file owner)
  • Owner group ID (GID of the file's group)
  • Inode number (unique identifier for the file in the file system, on Unix-like systems)
  • Device ID (identifier of the device containing the file)
  • Number of hard links (count of hard links pointing to the file)

Note: Some properties (e.g., inode, device ID) are read-only and cannot be written. Others (e.g., permissions, modification time) can be modified via system calls. The classes below will implement reading all properties and writing those that are modifiable. To "decode" in this context means to retrieve and interpret the raw values from the file system. The classes assume a Unix-like environment for consistency (e.g., Linux/macOS), as Windows has variations (e.g., no inode). They also verify the file extension is .asm (case-insensitive) to ensure it's a .ASM file.

2. Python Class

import os
import time
import stat

class ASMFileHandler:
    def __init__(self, filepath):
        self.filepath = os.path.abspath(filepath)
        if not self.filepath.lower().endswith('.asm'):
            raise ValueError("File must have .asm extension")
        if not os.path.exists(self.filepath):
            raise FileNotFoundError(f"File not found: {self.filepath}")

    def read_properties(self):
        st = os.stat(self.filepath)
        return {
            'file_path': self.filepath,
            'file_size': st.st_size,
            'creation_time': time.ctime(st.st_birthtime) if hasattr(st, 'st_birthtime') else 'Not supported',
            'modification_time': time.ctime(st.st_mtime),
            'access_time': time.ctime(st.st_atime),
            'permissions': stat.filemode(st.st_mode),
            'owner_uid': st.st_uid,
            'owner_gid': st.st_gid,
            'inode_number': st.st_ino,
            'device_id': st.st_dev,
            'num_hard_links': st.st_nlink
        }

    def write_properties(self, properties):
        # Write modifiable properties
        if 'modification_time' in properties:
            mtime = properties['modification_time']
            atime = os.stat(self.filepath).st_atime  # Preserve access time
            os.utime(self.filepath, (atime, mtime))
        if 'access_time' in properties:
            atime = properties['access_time']
            mtime = os.stat(self.filepath).st_mtime  # Preserve modification time
            os.utime(self.filepath, (atime, mtime))
        if 'permissions' in properties:
            os.chmod(self.filepath, properties['permissions'])
        if 'owner_uid' in properties or 'owner_gid' in properties:
            uid = properties.get('owner_uid', -1)
            gid = properties.get('owner_gid', -1)
            os.chown(self.filepath, uid, gid)
        # Read-only properties like size, inode, etc., cannot be written directly

3. Java Class

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.attribute.FileOwnerAttributeView;
import java.nio.file.attribute.FileTime;
import java.nio.file.attribute.PosixFileAttributeView;
import java.nio.file.attribute.PosixFileAttributes;
import java.nio.file.attribute.PosixFilePermission;
import java.nio.file.attribute.UserPrincipal;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class ASMFileHandler {
    private final Path filepath;

    public ASMFileHandler(String filepath) throws IOException {
        this.filepath = Paths.get(filepath).toAbsolutePath();
        if (!this.filepath.toString().toLowerCase().endsWith(".asm")) {
            throw new IllegalArgumentException("File must have .asm extension");
        }
        if (!Files.exists(this.filepath)) {
            throw new IOException("File not found: " + this.filepath);
        }
    }

    public Map<String, Object> readProperties() throws IOException {
        BasicFileAttributes basicAttrs = Files.readAttributes(filepath, BasicFileAttributes.class);
        PosixFileAttributes posixAttrs = Files.readAttributes(filepath, PosixFileAttributes.class);
        Map<String, Object> props = new HashMap<>();
        props.put("file_path", filepath.toString());
        props.put("file_size", basicAttrs.size());
        props.put("creation_time", basicAttrs.creationTime());
        props.put("modification_time", basicAttrs.lastModifiedTime());
        props.put("access_time", basicAttrs.lastAccessTime());
        props.put("permissions", posixAttrs.permissions());
        props.put("owner_uid", posixAttrs.owner());  // UserPrincipal, not numeric UID
        props.put("owner_gid", posixAttrs.group());  // GroupPrincipal, not numeric GID
        props.put("inode_number", basicAttrs.fileKey());  // Approximation, as Java doesn't expose inode directly
        props.put("device_id", "Not directly supported");
        props.put("num_hard_links", posixAttrs.isRegularFile() ? 1 : "Varies");  // Approximation
        return props;
    }

    public void writeProperties(Map<String, Object> properties) throws IOException {
        if (properties.containsKey("modification_time")) {
            Files.setLastModifiedTime(filepath, (FileTime) properties.get("modification_time"));
        }
        if (properties.containsKey("access_time")) {
            Files.setAttribute(filepath, "lastAccessTime", properties.get("access_time"));
        }
        if (properties.containsKey("permissions")) {
            PosixFileAttributeView view = Files.getFileAttributeView(filepath, PosixFileAttributeView.class);
            view.setPermissions((Set<PosixFilePermission>) properties.get("permissions"));
        }
        if (properties.containsKey("owner_uid")) {
            FileOwnerAttributeView view = Files.getFileAttributeView(filepath, FileOwnerAttributeView.class);
            view.setOwner((UserPrincipal) properties.get("owner_uid"));
        }
        if (properties.containsKey("owner_gid")) {
            PosixFileAttributeView view = Files.getFileAttributeView(filepath, PosixFileAttributeView.class);
            view.setGroup((UserPrincipal) properties.get("owner_gid"));  // GroupPrincipal
        }
        // Read-only properties cannot be written
    }
}

4. JavaScript Class (Node.js)

const fs = require('fs');
const path = require('path');

class ASMFileHandler {
    constructor(filepath) {
        this.filepath = path.resolve(filepath);
        if (!this.filepath.toLowerCase().endsWith('.asm')) {
            throw new Error('File must have .asm extension');
        }
        if (!fs.existsSync(this.filepath)) {
            throw new Error(`File not found: ${this.filepath}`);
        }
    }

    readProperties() {
        const st = fs.statSync(this.filepath);
        return {
            file_path: this.filepath,
            file_size: st.size,
            creation_time: st.birthtime,
            modification_time: st.mtime,
            access_time: st.atime,
            permissions: st.mode.toString(8),  // Octal string
            owner_uid: st.uid,
            owner_gid: st.gid,
            inode_number: st.ino,
            device_id: st.dev,
            num_hard_links: st.nlink
        };
    }

    writeProperties(properties) {
        if (properties.modification_time || properties.access_time) {
            const atime = properties.access_time || fs.statSync(this.filepath).atime;
            const mtime = properties.modification_time || fs.statSync(this.filepath).mtime;
            fs.utimesSync(this.filepath, atime, mtime);
        }
        if (properties.permissions) {
            fs.chmodSync(this.filepath, properties.permissions);
        }
        if (properties.owner_uid !== undefined || properties.owner_gid !== undefined) {
            const uid = properties.owner_uid ?? -1;
            const gid = properties.owner_gid ?? -1;
            fs.chownSync(this.filepath, uid, gid);
        }
        // Read-only properties cannot be written
    }
}

5. C++ Class

#include <iostream>
#include <string>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <utime.h>
#include <cstring>
#include <cerrno>
#include <map>
#include <ctime>

class ASMFileHandler {
private:
    std::string filepath;

public:
    ASMFileHandler(const std::string& fp) {
        filepath = std::string(std::realpath(fp.c_str(), nullptr));
        std::string ext = filepath.substr(filepath.find_last_of(".") + 1);
        std::transform(ext.begin(), ext.end(), ext.begin(), ::tolower);
        if (ext != "asm") {
            throw std::invalid_argument("File must have .asm extension");
        }
        struct stat st;
        if (stat(filepath.c_str(), &st) != 0) {
            throw std::runtime_error("File not found: " + filepath);
        }
    }

    std::map<std::string, std::string> readProperties() {
        struct stat st;
        stat(filepath.c_str(), &st);
        std::map<std::string, std::string> props;
        props["file_path"] = filepath;
        props["file_size"] = std::to_string(st.st_size);
        props["creation_time"] = std::string(ctime(&st.st_ctime)).erase(24);  // Remove newline
        props["modification_time"] = std::string(ctime(&st.st_mtime)).erase(24);
        props["access_time"] = std::string(ctime(&st.st_atime)).erase(24);
        char perm[10];
        snprintf(perm, sizeof(perm), "%o", st.st_mode & 0777);
        props["permissions"] = perm;
        props["owner_uid"] = std::to_string(st.st_uid);
        props["owner_gid"] = std::to_string(st.st_gid);
        props["inode_number"] = std::to_string(st.st_ino);
        props["device_id"] = std::to_string(st.st_dev);
        props["num_hard_links"] = std::to_string(st.st_nlink);
        return props;
    }

    void writeProperties(const std::map<std::string, long>& properties) {  // Use long for timestamps/IDs/modes
        if (properties.find("modification_time") != properties.end() || properties.find("access_time") != properties.end()) {
            struct stat st;
            stat(filepath.c_str(), &st);
            struct utimbuf times;
            times.actime = properties.find("access_time") != properties.end() ? properties.at("access_time") : st.st_atime;
            times.modtime = properties.find("modification_time") != properties.end() ? properties.at("modification_time") : st.st_mtime;
            utime(filepath.c_str(), &times);
        }
        if (properties.find("permissions") != properties.end()) {
            chmod(filepath.c_str(), properties.at("permissions"));
        }
        if (properties.find("owner_uid") != properties.end() || properties.find("owner_gid") != properties.end()) {
            uid_t uid = properties.find("owner_uid") != properties.end() ? properties.at("owner_uid") : -1;
            gid_t gid = properties.find("owner_gid") != properties.end() ? properties.at("owner_gid") : -1;
            chown(filepath.c_str(), uid, gid);
        }
        // Read-only properties cannot be written
    }
};