I am trying to create a C program in Turbo C++ 3.0 that will work on MS-DOS 6.22 and need to access CD-ROM using MSCDEX and interrupts, to play tracks on it.
Turbo C wasn't a problem for me and I already did it and it worked very well, but now I'm trying to use this documentation to get the name of the CD-ROM device driver.
Here is my code:
#include <stdio.h>
#include <dos.h>
void main(){
clrscr();
CDname();
printf("\nPress a button to exit the program.");
getch();
}
void CDname(){
char myArray[15];
int i;
asm{
mov AX,1501H
les BX,DWORD PTR[myArray]
int 2FH
}
for(i=0; i < 15; i++){
printf("\nArray = %c", myArray[i]);
}
}
And here is a little part of a documentation that I'm trying to follow:
How do I get the name of the CD-ROM device driver?
First, you need to know how many CD-ROMs you have (see question
2.01, How many CD-ROMs are present?). You need a block of memory
whose size, in bytes, is 5 times the number of CD-ROMs present.
This code will fill that array:
mov AX,1501H
les BX,DriverArray
int 2FH
Each 5-byte element in the array consists of the drive's subunit
number (a CD-ROM device driver may support several drives as
subunits), followed by the address of the drive's device driver.
The filename is 10 bytes into the device driver. The filename is
at most 8 bytes long, and if less than 8 bytes, is terminated by
a space (20H).
The problem is that I need to put CD-ROM name inside myArray but in this way I'm not pretty sure of what I am doing. Someone can help me to do it?
Thanks in advance!
If you first zero-out myarray using memset(), you'll find that the inline assembly isn't writing any info to that location. This is because the LES instruction is loading the far pointer into ES:BX from your uninitialized memory rather than setting the address of ES:BX to the memory which is what you want.
Those sample instructions assumed you had a far pointer in DriverArray. What the interrupt function is really expecting is for ES:BX to point to your array. Since ES already points to the data segment (as does DS and SS), simply load BX with the offset of your array on the stack using "lea bx,[myarray]".
When "int 2Fh" executes (at least on my virtual machine), it writes the following bytes to the myarray buffer:
00 00 00 EF 04
I assume the first byte must be the subunit and the remaining 4 bytes correspond to the far pointer 04EF:0000. In Turbo Debugger, this location on my machine had the following bytes:
04EF:0000 00 00 A8 03 00 C8 DC 00 E7 00 4D 53 43 44 30 30 ..........MSCD00
04EF:0010 30 20 00 00 04 01 00 4F 41 $B 20 41 54 41 50 49 0 .....OAK ATAPI
04EF:0020 20 49 44 45 20 43 44 2D 52 4F 4D 98 00 3F 15 3B IDE CD-ROM.....
You can see the driver filename is MSCD000 at offset 10, just like the instructions said.
Therefore, we just need to craft a structure from which you can dereference the far pointer to the CD-ROM info and add the 10 offset. Then you can specify your string using printf using the far string format specifier:
struct CDINFO
{
unsigned char subunit;
unsigned char far* pData;
};
...
printf("CDROM filename = \"%Fs\"\n",
((CDINFO*)myarray)->pData + 10
);
Here is the complete revised code:
NOTE: I didn't bother to display the CD-ROM filename without the terminating space. I'll leave that as an exercise to you to remove it or display any of the other CD-Rom driver strings. I also changed your array type from char to unsigned char because it was sign extending any byte >127 into a full word in the 15-byte debug-dump
#include <stdio.h>
#include <conio.h>
#include <dos.h>
#include <string.h>
//we'll superimpose this upon myarray
struct CDINFO
{
unsigned char subunit;
unsigned char far* pData;
};
void CDname()
{
unsigned char myarray[15];
int i;
//for debugging, ensure this buffer is initially clear
memset(myarray,0,sizeof(myarray));
asm {
mov ax,1501h
lea bx,[myarray]
int 2Fh
}
//notice the %Fs format specified specifies a "far" string
printf("CDROM filename = \"%Fs\"\n",
((CDINFO*)myarray)->pData + 10
);
//this is useful for debugging
for(i=0; i<sizeof(myarray); i++)
{
printf("Array = %02X\n",myarray[i]);
}
}
void main()
{
clrscr();
CDname();
printf("\nPress a button to exit the program.");
getch();
}
OUTPUT:
CDROM filename = "MSCD000 "
Array = 00
Array = 00
Array = 00
Array = EF
Array = 04
Array = 00
Array = 00
Array = 00
Array = 00
Array = 00
Array = 00
Array = 00
Array = 00
Array = 00
Array = 00
Press a button to exit the program.
UPDATE: When troubleshooting, I initially made myarray a global variable, accessing it using "mov bx,OFFSET myarray". However I didn't realize SS pointed to the data segment too, so I changed the source back to a version closer to the original where myarray is accessed as a local stack-based buffer.