Low-level PC Info Retrieval

You

in MSDOS on the PC I want to get some low level info about the computer, for example

  • The amount of RAM in the system
  • The CPU
  • Anything about the BIOS and motherboard

I am using DJGPP to write C code.

ChatGPT

Using DJGPP, you can retrieve low-level system information in MS-DOS by interacting with BIOS interrupts, the DOS API, and direct hardware queries. Here’s how you can gather some of the information you’re looking for:

1. Getting Total System RAM

You can use INT 12h to get the conventional memory size (first 640 KB) and INT 15h, AX=E801h or AX=E820h to get extended memory (beyond 1MB).

Example (Conventional Memory - INT 12h)

#include <dos.h>
#include <stdio.h>

int main() {
    union REGS regs;
    regs.h.ah = 0x12;
    int86(0x12, &regs, &regs);
    
    printf("Conventional Memory: %d KB\n", regs.x.ax);
    return 0;
}

Example (Extended Memory - INT 15h, E801h)

#include <dos.h>
#include <stdio.h>

int main() {
    union REGS regs;
    regs.x.ax = 0xE801;
    int86(0x15, &regs, &regs);
    
    if (regs.x.ax || regs.x.bx) {  // If BIOS supports it
        int extmem = (regs.x.ax * 64) + (regs.x.bx * 1024);
        printf("Extended Memory: %d KB\n", extmem);
    } else {
        printf("Extended Memory query failed.\n");
    }
    
    return 0;
}

If that doesn’t work, use INT 15h, AX=E820h for a more detailed memory map.

2. Detecting the CPU Type

DJGPP provides the __djgpp_cpuid variable, but you can also manually query CPUID (if supported) or check flags.

Example (Checking CPU using CPUID)

#include <stdio.h>

int main() {
    int eax, ebx, ecx, edx;
    __asm__ __volatile__ (
        "mov $0, %%eax\n\t"
        "cpuid\n\t"
        "mov %%eax, %0\n\t"
        "mov %%ebx, %1\n\t"
        "mov %%ecx, %2\n\t"
        "mov %%edx, %3\n\t"
        : "=r" (eax), "=r" (ebx), "=r" (ecx), "=r" (edx)
        :
        : "eax", "ebx", "ecx", "edx"
    );

    printf("CPU Vendor: %.4s%.4s%.4s\n", (char*)&ebx, (char*)&edx, (char*)&ecx);
    return 0;
}

This retrieves the CPU vendor string (e.g., “GenuineIntel” or “AuthenticAMD”).

3. Getting BIOS and Motherboard Info

You can retrieve BIOS-related information from the BIOS Data Area (BDA) at segment 40h.

Example (BIOS Manufacturer Date and Model from F000:FFF5)

#include <stdio.h>

char* get_bios_date() {
    return (char*)0xF000FFF5;
}

int main() {
    printf("BIOS Date: %s\n", get_bios_date());
    return 0;
}

This returns the BIOS release date as a string.

For more detailed BIOS information, scan the BIOS ROM for identifiers, or use INT 1Ah (real-time clock) to get some system details.

4. Getting the Motherboard Manufacturer

If your BIOS supports DMI (Desktop Management Interface), you can use INT 15h, AX=0xD000 to query SMBIOS.

However, older systems may not support this, and you might need to parse raw BIOS data.

Final Thoughts

  • Some of these methods may not work on every system, especially very old PCs without CPUID or SMBIOS support.
  • INT 15h
  • Reading

Would you like more advanced methods, such as reading PCI configuration space or scanning the BIOS ROM for specific signatures?

ChatGPT

Getting a Detailed Memory Map Using INT 15h, AX=E820h

The BIOS interrupt INT 15h, AX=E820h provides a detailed memory map of the system. Unlike older methods (such as INT 12h or INT 15h, AX=E801h), which only report total memory, E820h returns a list of memory regions, including reserved, usable, and special memory areas.

How INT 15h, AX=E820h Works

  1. You call
  2. You pass a memory buffer for the BIOS to fill with information.
  3. You retrieve multiple memory entries by calling it repeatedly with an index.
  4. Each entry describes a specific memory range and its type.

This method allows you to:

  • Identify all
  • Detect reserved memory areas (e.g., BIOS, MMIO regions).
  • Detect ACPI and other special areas.

Memory Map Entry Structure

Each call to INT 15h, AX=E820h returns a memory map entry in the following format:

Offset Size Description
0x00 4 Base address (low 32 bits)
0x04 4 Base address (high 32 bits)
0x08 4 Length in bytes (low 32 bits)
0x0C 4 Length in bytes (high 32 bits)
0x10 4 Type (1 = usable, other = reserved)
0x14 4 (Optional) Extended attributes

The type field tells you how the memory can be used:

  • 1 → Usable (RAM)
  • 2 → Reserved (BIOS, MMIO)
  • 3 → ACPI reclaimable memory
  • 4 → ACPI NVS memory (used for power management)
  • 5 → Defective memory (bad RAM)

Example C Code Using DJGPP

Since DJGPP runs in protected mode, we need to switch to real mode (using a DOS extender like CWSDPMI) or use a DOS interrupt call via int86x.

Here’s how you can retrieve the memory map:

#include <dos.h>
#include <stdio.h>

struct E820_Entry {
    unsigned long base_low;
    unsigned long base_high;
    unsigned long length_low;
    unsigned long length_high;
    unsigned long type;
} __attribute__((packed));

int main() {
    struct E820_Entry entry;
    union REGS regs;
    struct SREGS sregs;
    unsigned long contID = 0;

    printf("Base Address       | Length            | Type\n");
    printf("-------------------+-------------------+------\n");

    do {
        regs.x.ax = 0xE820;  // Function: Get System Memory Map
        regs.x.cx = sizeof(entry);
        regs.x.edx = 0x534D4150;  // 'SMAP' magic number
        regs.x.ebx = contID;  // Continuation ID (0 on first call)
        sregs.es = FP_SEG(&entry);
        regs.x.di = FP_OFF(&entry);

        int86x(0x15, &regs, &regs, &sregs);  // Call INT 15h

        if (regs.x.eflags & 1) break;  // Check carry flag (CF) for errors

        contID = regs.x.ebx;  // Store continuation ID for next call

        printf("%08lX%08lX | %08lX%08lX | %lu\n",
               entry.base_high, entry.base_low,
               entry.length_high, entry.length_low,
               entry.type);

    } while (contID != 0);  // Continue until EBX returns 0

    return 0;
}

Explanation of Code

  1. We define a struct E820_Entry
  2. We set up registers for the BIOS call
  • AX = E820h
  • CX = sizeof(entry)
  • EDX = ‘SMAP’
  • EBX = contID
  • ES:DI
  1. We call INT 15h using int86x
  2. We check the carry flag (CF)
  • If set, the BIOS call failed.
  1. We loop until EBX returns 0

Interpreting the Output

Example output might look like this:

Base Address       | Length            | Type
-------------------+-------------------+------
0000000000000000 | 000000000009FC00 | 1  (Usable)
000000000009FC00 | 0000000000000400 | 2  (Reserved - BIOS)
00000000000F0000 | 0000000000010000 | 2  (Reserved - BIOS)
0000000000100000 | 0000000003FF0000 | 1  (Usable RAM)
00000000FFFC0000 | 0000000000040000 | 2  (Reserved - BIOS)

This shows:

  • Conventional RAM
  • BIOS Reserved Areas
  • Usable Extended RAM

Advantages of Using INT 15h, AX=E820h

  • ✅ More accurate than INT 12h or E801h → These older methods only return total RAM and might not account for reserved memory.
  • ✅ Provides multiple memory regions → Helps OS developers manage usable vs. reserved memory.
  • ✅ Works on most BIOSes from 1995 onward → Newer machines with UEFI might require different methods.

Limitations

❌ Requires BIOS support → Some old PCs (pre-1995) don’t support it.❌ Must handle multiple entries → Unlike INT 12h, which just gives a single value.❌ Protected mode limitations in DJGPP → Requires int86x and segment register handling.

Would you like an explanation on how to use INT 1Ah for RTC BIOS time or PCI BIOS functions for motherboard detection?

You

yes

ChatGPT

Getting BIOS and Motherboard Information in MS-DOS using C (DJGPP)

To retrieve low-level system information like BIOS details, real-time clock (RTC), and motherboard details, we can use BIOS interrupts such as INT 1Ah and PCI BIOS functions (INT 1Ah, AX=B101h).

  1. Getting the Real-Time Clock (RTC) with INT 1Ah

The real-time clock (RTC) is stored in the CMOS (Complementary Metal-Oxide Semiconductor) chip and keeps track of the system’s date and time, even when powered off.

How INT 1Ah Works

  1. Call INT 1Ah with AH = 00h to get the current time.
  2. The BIOS returns:
  • CH
  • CL
  • DH
  1. Convert the BCD values to decimal.

Example C Code to Get Time

#include <dos.h>
#include <stdio.h>

int bcd_to_decimal(int bcd) {
    return ((bcd >> 4) * 10) + (bcd & 0x0F);
}

int main() {
    union REGS regs;
    
    // Call INT 1Ah, AH = 00h (Get RTC Time)
    regs.h.ah = 0x00;
    int86(0x1A, &regs, &regs);

    int hours = bcd_to_decimal(regs.h.ch);
    int minutes = bcd_to_decimal(regs.h.cl);
    int seconds = bcd_to_decimal(regs.h.dh);

    printf("Current RTC Time: %02d:%02d:%02d\n", hours, minutes, seconds);
    
    return 0;
}

Example Output

Current RTC Time: 14:23:45
  1. Getting Motherboard and BIOS Information

Some details about the BIOS and motherboard can be retrieved using INT 1Ah, AX=B101h (PCI BIOS services) or by reading the BIOS Data Area (BDA) at 0xF000:0FFF.

Detecting PCI BIOS with INT 1Ah

If your system has PCI devices, the PCI BIOS provides information about the system, including motherboard chipset details.

How INT 1Ah, AX=B101h Works

  1. Call
  2. If PCI BIOS is available, it returns:
  • BX = “PCI” signature (0x20494350)
  • CL = PCI hardware version
  • CH = Number of PCI buses
  • ES:DI = Pointer to PCI Service Structure

Example C Code for PCI BIOS Detection

#include <dos.h>
#include <stdio.h>

int main() {
    union REGS regs;
    
    // Call INT 1Ah, AX = B101h (PCI BIOS Present)
    regs.x.ax = 0xB101;
    int86(0x1A, &regs, &regs);

    // Check if PCI BIOS is available
    if (regs.x.bx == 0x20494350) {  // 'PCI ' signature
        printf("PCI BIOS detected\n");
        printf("PCI Hardware Version: %d.%d\n", regs.h.ch, regs.h.cl);
        printf("Number of PCI Buses: %d\n", regs.h.ch);
    } else {
        printf("PCI BIOS not available\n");
    }

    return 0;
}

Example Output

PCI BIOS detected
PCI Hardware Version: 2.1
Number of PCI Buses: 1

This indicates that:

  • The system supports PCI BIOS.
  • The PCI hardware version is
  • There is
  1. Reading BIOS Manufacturer and Motherboard Details

The BIOS manufacturer string is stored in the BIOS ROM at segment 0xF000.

Reading BIOS Information from Memory

  • BIOS Date
  • BIOS Manufacturer

Example C Code to Read BIOS Date

#include <stdio.h>
#include <dos.h>

int main() {
    char far *bios_date = (char far *)0xF000FFF5;  // Standard location of BIOS date
    printf("BIOS Date: %.8s\n", bios_date);
    return 0;
}

Example Output

BIOS Date: 09/14/99

This indicates that the BIOS was last updated on September 14, 1999.

Summary

Method Purpose
INT 1Ah, AH=00h Get RTC time
INT 1Ah, AX=B101h Detect PCI BIOS
0xF000:0FFF Read BIOS date
E820h Get memory map

Would you like to explore CPU detection next (e.g., CPUID)?

You

ChatGPT

Reading the BIOS Manufacturer String in MS-DOS with DJGPP

How to Get the BIOS Manufacturer Information

The BIOS Manufacturer is often stored as ASCII text in the BIOS ROM, usually in the F000:0000–F000:FFFF segment of memory (the BIOS ROM area). However, its exact location varies by manufacturer. Some BIOS versions store a human-readable string at 0xF000:FFF5, alongside the BIOS date.

Since DJGPP runs in protected mode, we must use a DOS interrupt or switch to real-mode memory access to read from this area.

Method 1: Direct Memory Access (Only Works in Real Mode)

If you were writing a real-mode DOS program (e.g., using Turbo C or OpenWatcom), you could access the BIOS ROM directly using a far pointer:

#include <stdio.h>
#include <dos.h>

int main() {
    char far *bios_string = (char far *)0xF000E000;  // Possible location in BIOS ROM
    printf("BIOS String: %.16s\n", bios_string);  // Print first 16 characters
    return 0;
}

However, this does not work in DJGPP, since DJGPP runs in a 32-bit protected mode environment.

Method 2: Using the DOS Real-Mode Memory Transfer

Since DJGPP runs in protected mode, we need to use int 0x15 (BIOS memory functions) or DPMI (DOS Protected Mode Interface) to access real-mode memory.

Example: Using int86() to Get BIOS Information

This code calls a DOS interrupt (INT 15h) to get the BIOS memory area.

#include <stdio.h>
#include <dos.h>

int main() {
    union REGS regs;
    
    // Set function: INT 15h, AX=E820h (Get Memory Map)
    regs.x.ax = 0xE820;
    regs.x.cx = 0;  // Size of buffer
    regs.x.dx = 0x534D4150; // 'SMAP' signature
    
    int86(0x15, &regs, &regs);
    
    if (regs.x.eax == 0x534D4150) {  // Check if 'SMAP' returned correctly
        printf("BIOS Memory Map Function Available\n");
    } else {
        printf("BIOS Memory Map Function Not Supported\n");
    }

    return 0;
}

This doesn’t directly read the BIOS string but verifies if we can access BIOS memory-mapped information.

To directly get the BIOS manufacturer, you’d need a DPMI real-mode memory call, which requires DPMI services.

Would you like an example using DPMI real-mode calls to fetch BIOS data?

Now, About CPUID

The CPUID instruction provides detailed information about the CPU, such as:

  • Vendor string
  • Processor family, model, and stepping
  • Feature flags

CPUID is only available on 486+ processors, so it must be checked first.

How to Use CPUID

  1. Set EAX to a function number
  2. Execute CPUID instruction
  3. Read back EAX, EBX, ECX, and EDX

Example CPUID in DJGPP

DJGPP does not allow inline assembly with cpuid directly. Instead, we must use inline assembly with GCC extended syntax:

#include <stdio.h>

void cpuid(int code, unsigned int *a, unsigned int *b, unsigned int *c, unsigned int *d) {
    __asm__ __volatile__ (
        "cpuid"
        : "=a"(*a), "=b"(*b), "=c"(*c), "=d"(*d)
        : "a"(code)
    );
}

int main() {
    unsigned int eax, ebx, ecx, edx;
    
    // CPUID function 0: Get vendor ID
    cpuid(0, &eax, &ebx, &ecx, &edx);
    
    char vendor[13];
    *((unsigned int*)&vendor[0]) = ebx;
    *((unsigned int*)&vendor[4]) = edx;
    *((unsigned int*)&vendor[8]) = ecx;
    vendor[12] = '\0';
    
    printf("CPU Vendor: %s\n", vendor);
    
    return 0;
}

Example Output

CPU Vendor: GenuineIntel

If running on an AMD CPU:

CPU Vendor: AuthenticAMD

Would you like more details on checking CPU features (e.g., MMX, SSE, etc.)?

You

in MSDOS on the PC I want to get some low level info about the computer, for example

The amount of RAM in the system The CPU Anything about the BIOS and motherboard

I am now using Turbo C 3.0 in DOS to write C code.

ChatGPT

Great! Since you’re now using Turbo C 3.0 in MS-DOS, you can access low-level system information like the amount of RAM, CPU type, and BIOS using interrupts and direct memory access.

Here’s how you can get this information using Turbo C 3.0:

  1. Getting the Amount of RAM

MS-DOS provides an interrupt for getting memory information:

  • INT 12h

Getting the Total RAM with INT 12h

#include <dos.h>
#include <stdio.h>

int main() {
    union REGS regs;
    
    // Call INT 12h to get the amount of installed RAM
    regs.h.ah = 0x00;
    int86(0x12, &regs, &regs);
    
    // The total memory is in the AX register (in KB)
    printf("Total RAM: %u KB\n", regs.x.ax);
    
    return 0;
}

Explanation:

  • INT 12h
  • AX register
  1. Detecting the CPU Type

The CPUID instruction is not directly available in Turbo C 3.0, but you can still detect the CPU type using the ID string or vendor information that INT 15h (Extended BIOS functions) provides.

To get basic CPU information, Turbo C 3.0 can use INT 15h, AX=87h:

Getting CPU Information (Vendor)

#include <dos.h>
#include <stdio.h>

int main() {
    union REGS regs;
    char vendor[13];
    
    // Call INT 15h, AX=87h to get CPU information
    regs.x.ax = 0x8700;
    int86(0x15, &regs, &regs);
    
    // Return the CPU Vendor string from the DX register
    *((unsigned int*)&vendor[0]) = regs.x.dx;
    *((unsigned int*)&vendor[4]) = regs.x.bx;
    *((unsigned int*)&vendor[8]) = regs.x.cx;
    vendor[12] = '\0';
    
    printf("CPU Vendor: %s\n", vendor);
    
    return 0;
}

Explanation:

  • INT 15h, AX=87h
  • The
  1. Getting BIOS Information

The BIOS Manufacturer String and other related information can be retrieved by reading the BIOS data area (located at segment 0xF000).

You can directly access BIOS data using a far pointer to read the BIOS version or manufacturer.

Getting BIOS Date and Manufacturer

#include <stdio.h>
#include <dos.h>

int main() {
    char far *bios_string = (char far *)0xF000E000;  // Possible location in BIOS ROM
    char far *bios_date = (char far *)0xF000FFF5;    // Standard location of BIOS date
    
    printf("BIOS Manufacturer: %.16s\n", bios_string);
    printf("BIOS Date: %.8s\n", bios_date);
    
    return 0;
}

Explanation:

  • 0xF000E000
  • 0xF000FFF5
  • The string length is limited to the maximum readable portion from memory, typically
  1. Getting Motherboard Information

Motherboard-specific information is typically harder to retrieve directly from DOS, as there is no standard interrupt for querying motherboard details. However, you can use INT 1Ah (BIOS interrupt for PCI) for some PCI information if your motherboard supports it.

For basic motherboard information, BIOS Interrupts like INT 1Ah can provide details about the PCI system.

Checking for PCI Information via INT 1Ah

#include <stdio.h>
#include <dos.h>

int main() {
    union REGS regs;
    
    // Call INT 1Ah, AX=B101h to check PCI system info
    regs.x.ax = 0xB101;
    int86(0x1A, &regs, &regs);
    
    if (regs.x.bx == 0x20494350) {  // Check for 'PCI ' signature
        printf("PCI BIOS detected\n");
    } else {
        printf("PCI BIOS not available\n");
    }
    
    return 0;
}

Explanation:

  • INT 1Ah, AX=0xB101
  • The

Summary of Key Interrupts for Low-Level Info:

Info Type Interrupt Function
Total RAM INT 12h Returns total RAM in KB (in AX)
CPU Vendor INT 15h, AX=87h Returns CPU vendor string in DX, BX, CX
BIOS Manufacturer Far pointer at 0xF000E000 Reads BIOS Manufacturer String
BIOS Date Far pointer at 0xF000FFF5 Reads BIOS Date String
PCI Info INT 1Ah, AX=B101h Detects PCI BIOS availability

These are the methods you can use to get the RAM size, CPU information, and BIOS/motherboard details in Turbo C 3.0 under MS-DOS. Let me know if you want to dive deeper into any specific area!

You

what can I read from the PCI BIOS? Can I read the strings of text the BIOS normally displays at boot?

ChatGPT

Accessing PCI BIOS Information

The PCI BIOS (part of the system BIOS responsible for managing PCI devices) can provide several pieces of information about the system’s hardware, particularly related to PCI devices (like graphics cards, network adapters, etc.). However, reading strings of text displayed during boot (like the BIOS POST screen) is a bit different and typically not available through PCI BIOS or standard BIOS calls.

Let’s break it down:

  1. PCI BIOS Information

PCI BIOS provides low-level information related to the PCI devices installed in the system. Some common types of information you can get from the PCI BIOS include:

  • List of PCI Devices
  • Device Vendor ID
  • Device Class Code
  • PCI Configuration Space

To access PCI BIOS information in real mode (which is how Turbo C 3.0 runs), you’d typically use INT 1Ah, but this doesn’t directly allow you to access strings like those shown on the boot screen. Here’s what you can typically retrieve:

Reading PCI Information via INT 1Ah

The PCI BIOS provides access to device information through INT 1Ah, and here’s how you can query it:

#include <stdio.h>
#include <dos.h>

int main() {
    union REGS regs;
    unsigned int vendorID, deviceID;
    
    // Call INT 1Ah, AX=0xB101 to get PCI information
    regs.x.ax = 0xB101; // PCI BIOS signature
    int86(0x1A, &regs, &regs);
    
    if (regs.x.bx == 0x20494350) {  // Check for 'PCI ' signature
        printf("PCI BIOS found!\n");
        
        // Call the PCI function to get a device's vendor ID and device ID
        regs.x.ax = 0xB100; // Function to get device info
        regs.x.bx = 0x0000; // Start with the first device
        int86(0x1A, &regs, &regs);
        
        vendorID = regs.x.cx;  // Vendor ID in CX
        deviceID = regs.x.dx;  // Device ID in DX
        
        printf("Vendor ID: 0x%04X\n", vendorID);
        printf("Device ID: 0x%04X\n", deviceID);
    } else {
        printf("PCI BIOS not found!\n");
    }
    
    return 0;
}

Explanation:

  • INT 1Ah
  • AX=0xB101
  • AX=0xB100

However, this approach focuses on querying PCI devices rather than reading BIOS messages shown during boot.

  1. Reading BIOS Text Displayed at Boot

The text that is displayed during the POST (Power-On Self-Test) phase of booting, such as the manufacturer logo, memory check, and device detection messages, is typically generated by the BIOS during the boot sequence. Unfortunately, there is no simple way to directly read those strings using BIOS interrupts in real mode, especially in Turbo C.

Here are the primary reasons:

  • BIOS screen output
  • BIOS POST
  • No interrupt

Can You Capture Boot Messages?

To capture the messages displayed during the BIOS POST phase, you would need to either:

  1. Log output during boot
  2. Modify the BIOS

Alternative Approaches to Get BIOS Information (Without POST Output)

While you can’t directly capture the POST boot text from the BIOS, there are other ways to get low-level system information about the BIOS, motherboard, and system setup.

  1. BIOS Manufacturer and Version
  • You can access the
  1. Motherboard Info
  • While there’s no specific BIOS interrupt for
  1. Serial Numbers

Summary

  • PCI Information
  • BIOS Strings
  • Boot Messages

Let me know if you’d like to dive deeper into any of these topics or need further assistance!

You

Can I read the motherboard type and bios revision and manufacturer from anywhere?

ChatGPT

In MS-DOS, there is no simple, standardized method to directly read detailed motherboard type and BIOS revision/manufacturer like you would expect in modern systems with ACPI or SMBIOS. However, there are some methods you can use to gather BIOS and system information, especially related to the BIOS manufacturer and revision. Let’s explore these methods in more detail:

  1. BIOS Manufacturer and Revision

You can often retrieve BIOS manufacturer and BIOS version/revision from certain memory locations in the BIOS ROM. This information is available in far memory segments starting from 0xF000, which is where the BIOS ROM is typically located.

Reading BIOS Manufacturer and Version

  • BIOS Manufacturer
  • BIOS Revision/Version

Here’s an example of how you might read these values using Turbo C 3.0:

#include <stdio.h>
#include <dos.h>

int main() {
    char far *bios_manufacturer = (char far *)0xF000E000;  // Manufacturer at this address
    char far *bios_revision = (char far *)0xF000FFE0;      // Revision/Version at this address
    
    // Print the Manufacturer and Revision string (ensure the string is null-terminated)
    printf("BIOS Manufacturer: %.16s\n", bios_manufacturer);
    printf("BIOS Revision: %.8s\n", bios_revision);
    
    return 0;
}

Explanation:

  • 0xF000E000
  • 0xF000FFE0

What You Get:

  • BIOS Manufacturer
  • BIOS Revision
  1. PCI BIOS and Motherboard Information

While PCI BIOS doesn’t provide direct motherboard information, it can give you clues about the PCI devices (e.g., integrated graphics, network cards, etc.) that are often part of the motherboard. Some systems store motherboard information in the PCI configuration space, which can be queried, but this is less common.

You can use INT 15h, AX=87h to get the PCI BIOS string, which may give a hint if the motherboard is managing PCI devices.

Example for querying PCI information:

#include <stdio.h>
#include <dos.h>

int main() {
    union REGS regs;
    char vendor[13];
    
    // Call INT 15h, AX=87h to get PCI information
    regs.x.ax = 0x8700;
    int86(0x15, &regs, &regs);
    
    // Return the PCI Vendor string from the DX register
    *((unsigned int*)&vendor[0]) = regs.x.dx;
    *((unsigned int*)&vendor[4]) = regs.x.bx;
    *((unsigned int*)&vendor[8]) = regs.x.cx;
    vendor[12] = '\0';
    
    printf("PCI BIOS Vendor: %s\n", vendor);
    
    return 0;
}

What You Can Get:

  • PCI Vendor
  1. System Setup (CMOS)

Another source of system information is the CMOS (the small configuration memory used by the system). This is where settings like the system date, time, and boot configuration are stored. It’s often accessed via INT 1Ah for certain system configuration operations.

While CMOS doesn’t give direct motherboard info, it could provide clues about certain system features (like RAM size and CPU settings).

  1. Accessing DMI or SMBIOS Information

Unfortunately, DMI (Desktop Management Interface) and SMBIOS (System Management BIOS), which store detailed system information like motherboard type, BIOS version, manufacturer, etc., are not available in MS-DOS.

These interfaces are a modern feature typically used by Windows and other modern operating systems. They allow access to detailed hardware information, including the motherboard manufacturer, BIOS revision, CPU info, and more, but in MS-DOS, you cannot access this data directly.

  1. Limitations in MS-DOS
  • BIOS
  • Motherboard
  • PCI BIOS

Summary

  1. BIOS Manufacturer and Version
  2. Motherboard Information
  3. PCI Devices

If you’re interested in more details about PCI devices or how to query other types of system information, feel free to ask!

You

What other potentially interesting things can I read out of my PC? let’s say I want to make some sort of diagnostics program.

So far I can find out the CPU, RAM, things from the BIOS. What about display info and attached storage devices?

ChatGPT

To create a diagnostics program in MS-DOS, you’re somewhat limited by the capabilities of real-mode interrupts and the available hardware abstraction layers. That being said, there are still a lot of interesting things you can query from your PC’s hardware. Below are some additional hardware details you can access, including display and storage information.

  1. Display Information

While you can’t directly query a lot of details about modern graphics hardware in MS-DOS, you can gather some basic information about the video mode and video memory.

Video Mode and Screen Resolution:

You can use INT 10h (Video BIOS interrupt) to query the current video mode, which tells you the resolution and color depth.

  • INT 10h, AH=0x0F
  • INT 10h, AH=0x0F

Example:

#include <stdio.h>
#include <dos.h>

int main() {
    union REGS regs;
    unsigned char video_mode;

    // Get current video mode
    regs.h.ah = 0x0F;  // Get video mode
    int86(0x10, &regs, &regs);
    video_mode = regs.h.al;  // AL contains the video mode number

    printf("Current Video Mode: 0x%02X\n", video_mode);
    
    // Depending on the mode, you can interpret resolution
    if (video_mode == 0x13) {
        printf("320x200, 256 colors (VGA mode)\n");
    } else if (video_mode == 0x03) {
        printf("80x25, 16 colors (Text mode)\n");
    } else {
        printf("Other mode\n");
    }

    return 0;
}

Video Memory:

You can inspect the amount of video memory using VGA memory in text mode or graphic mode. VGA typically uses 0xA000 to 0xAFFFF (64 KB) for graphics.

In graphics modes (such as mode 0x13), the video memory could be larger, and you can access the memory directly, but you’d need to map it correctly to handle it.

  • 0xA000–0xAFFFF
  • Video modes beyond this (like
  1. Storage Devices

While modern operating systems (like Windows or Linux) use advanced storage access methods like SATA, AHCI, or NVMe, MS-DOS uses INT 13h for basic disk operations. You can get information about attached storage devices (such as hard drives and floppy drives) using this interrupt.

Checking for Attached Drives (INT 13h)

Use INT 13h (disk services) to get disk drive parameters (such as the number of sectors, cylinders, heads) and disk type.

  • INT 13h, AH=0x08
  • INT 13h, AH=0x15

Here’s an example that queries drive parameters (you can check the drive’s type, size, and other info):

#include <stdio.h>
#include <dos.h>

int main() {
    union REGS regs;
    struct SREGS sregs;

    regs.h.ah = 0x08;  // Get drive parameters
    regs.h.al = 0x80;  // First hard drive (0x80 is typically the first hard disk)
    int86x(0x13, &regs, &regs, &sregs);

    if (regs.h.ah == 0) {
        printf("Drive Parameters Retrieved!\n");
        printf("Drive Type: 0x%02X\n", regs.h.al);
        printf("Heads: %u\n", regs.x.bx);
        printf("Cylinders: %u\n", regs.x.cx);
        printf("Sectors per track: %u\n", regs.x.dx);
    } else {
        printf("Error retrieving drive parameters!\n");
    }

    return 0;
}

What You Can Retrieve with INT 13h:

  • Drive Type
  • Drive Parameters
  • Disk Size
  1. Storage Information: Extended (Larger Hard Drives)

For modern large hard drives, INT 13h can be used, but extended BIOS services are needed for handling drives beyond the traditional 504MB limit. This is where INT 13h, AH=0x15 comes in, which is used to query extended information for large disks.

  • INT 13h, AH=0x15
  1. Serial Ports and COM Devices

If you want to get information about serial ports or COM devices connected to the system, you can use the INT 14h (serial port BIOS interrupt). This can give you access to various settings of the serial communication ports.

  • INT 14h
  • INT 14h, AH=0x0F

Example:

#include <stdio.h>
#include <dos.h>

int main() {
    union REGS regs;
    
    regs.h.ah = 0x0F;  // Get current configuration of COM ports
    regs.h.al = 0x01;  // COM1
    int86(0x14, &regs, &regs);

    printf("COM1 Port Status:\n");
    printf("Port is %s\n", (regs.h.al & 0x01) ? "Open" : "Closed");
    printf("Interrupt: 0x%02X\n", regs.h.bl);  // Interrupt vector for the port

    return 0;
}
  1. Network Adapters (via NDIS or other drivers)

In MS-DOS, network adapters (Ethernet cards, for example) usually require NDIS drivers to function. These drivers may provide their own methods for querying adapter information (like MAC addresses or configuration details). Unfortunately, querying detailed network interface information directly from BIOS or standard interrupts is not typically possible without the appropriate drivers being loaded.

You can try reading configuration files or using third-party drivers to fetch network-related diagnostics.

  1. System Timer and Performance Data
  • INT 1Ah, AH=0x00
  1. Power Management Information

While MS-DOS doesn’t have advanced power management access, you could potentially infer some low-level information from the CMOS setup (e.g., battery status) by accessing the CMOS using INT 1Ah (System Configuration).

  1. Sound Devices

In MS-DOS, you would typically need to interact with specific sound card drivers (like Sound Blaster) to retrieve information about sound devices. Using interrupts like INT 22h may give you some access, but again, the exact information you’d want (like sound card details) depends on the specific driver in use.

Summary

Here’s what you can potentially query for a diagnostics program in MS-DOS:

  • BIOS Information
  • CPU
  • RAM
  • Display
  • Storage
  • Network Adapters
  • Serial Ports
  • Power/Performance

Let me know if you’d like to explore any of these topics in greater depth or need help with the code!