gonx
asked on
Need help on converting assembler to inline assembly
Im sort of a newbie on this.. need help on having this code in inline assembler for Visual C++ 6.0.. ive been trying to understand why the msdev hangs when it reaches INT 21h after i some of the 16 bit registers to 32 e.g eax,ebx,edi etc..
C++ code is as follows:
#include <stdio.h>
#include "drivesex.h"
main()
{
int i;
Drives_Exist();
for (i = 0; i < 26; i++)
{
if (drives[i<<2] == DRIVEXISTS)
{
printf("%c: ",i+65);
printf("%s ",drives[(i<<2)+1] == 0 ? "Removable" : "Fixed ");
switch (drives[(i<<2)+2])
{
case LOCALDRV :printf("Local ");
break;
case REMOTEDRV:printf("Remote ");
break;
case SHAREDRV :printf("Shared ");
break;
}
switch (drives[(i<<2)+3])
{
case FLOPPY:printf("Floppy");
break;
case HARD :printf("Hard");
break;
case RAM :printf("RAM");
break;
case SUBST :printf("Subst");
break;
case CDROM :printf("CD-ROM");
break;
}
printf("\n");
}
}
}
the asm code is included separately as an ASM file:
; DRIVESEX.ASM - Drive existence detection July 6th, 1994
; Code by : Lee Hamel (hamell@cs.pdx.edu)
; Partial credit: Paul Schlyter
;
; Goes through drives A-Z and determines if they:
; 1) Exist
; 2) Are removable or fixed
; 3) Are local, remote, or shared
; 4) Are a floppy, hard, RAM, subst, or CD-ROM drive
;
; Callable from C as: void Drives_Exist(void);
.model small
.286
DRIVEEXIST EQU 1
REMOVEDRV EQU 0
FIXEDDRV EQU 1
LOCALDRV EQU 0
REMOTEDRV EQU 1
SHAREDRV EQU 2
FLOPPY EQU 0
HARD EQU 1
RAM EQU 2
SUBST EQU 3
CDROM EQU 4
.data
PUBLIC _drives
_drives db 26 dup(0,1,0,1)
; default to not exist, fixed, local, hard drive
.code
PUBLIC _Drives_Exist
_Drives_Exist PROC NEAR
pusha
push es
mov ah,19h
int 21h ; get start drive
push ax ; save start drive
mov ax,40h
mov es,ax
mov bh,es:[10h] ; 40:10h is # of floppies-1
shr bh,6
inc bh ; # of actual floppy drives
mov bl,1
mov di,offset _drives
nextchkfloppy: mov ax,4409h ; check if drive exists
int 21h
jc nextsetfloppy
test dh,10000000b ; check if SUBST drive
jz chkfloppy
dec bh ; dec actual drive count
mov byte ptr [di+3],SUBST
setfloppyexist: mov byte ptr [di],DRIVEEXIST
jmp nextsetfloppy
chkfloppy: dec bh ; dec actual drive count
js nextsetfloppy
mov byte ptr [di+1],REMOVEDRV
mov byte ptr [di+3],FLOPPY
jmp setfloppyexist
nextsetfloppy: add di,4
inc bl
cmp bl,2 ; if B then jump back
je nextchkfloppy
mov ch,24 ; loop 24 times (drives C - Z)
mov cl,3 ; start at C:
drivechkloop: mov ax,4409h ; check if drive exists
mov bl,cl ; set drive letter
int 21h ; 0 = default, 1 = A:, etc.
jc nextsetdrv
mov byte ptr [di],DRIVEEXIST
mov ax,4408h ; check if removable
int 21h
mov byte ptr [di+1],al ; set REMOVABLE or FIXED
mov bx,dx
mov dl,dh
shr dl,7
and dh,00010000b
shr dh,4
mov byte ptr [di+2],dh ; set REMOTE or LOCAL
or dl,dl ; if not SUBST, then jump
jz chkremote
mov byte ptr [di+3],SUBST
jmp nextsetdrv
chkremote: cmp dh,REMOTEDRV ; if REMOTE, then check for CD ROM
je chkcdrom
test bh,00000010b ; sharable?
jz drivenoshare
mov byte ptr [di+2],SHAREDRV
drivenoshare: test bl,00000010b ; RAM drive?
jnz nextsetdrv
mov byte ptr [di+3],RAM
jmp nextsetdrv
chkcdrom: push cx
mov ax,1500h
xor bx,bx
int 2fh
pop cx
or bx,bx ; MSCDEX driver found?
jz nextsetdrv ; if not, jump to next drive setup
mov ax,150bh
dec cl ; 0=A:, etc.
int 2fh
inc cl
or ax,ax
jz nextsetdrv ; drive supported by MSCDEX?
mov byte ptr [di+3],CDROM
nextsetdrv: add di,4
inc cl
dec ch
jnz drivechkloop
pop dx
mov ah,0eh
int 21h ; reset start drive
pop es
popa
ret
_Drives_Exist ENDP
END
Thanks.. i would be grateful to anyone who can answer..
C++ code is as follows:
#include <stdio.h>
#include "drivesex.h"
main()
{
int i;
Drives_Exist();
for (i = 0; i < 26; i++)
{
if (drives[i<<2] == DRIVEXISTS)
{
printf("%c: ",i+65);
printf("%s ",drives[(i<<2)+1] == 0 ? "Removable" : "Fixed ");
switch (drives[(i<<2)+2])
{
case LOCALDRV :printf("Local ");
break;
case REMOTEDRV:printf("Remote ");
break;
case SHAREDRV :printf("Shared ");
break;
}
switch (drives[(i<<2)+3])
{
case FLOPPY:printf("Floppy");
break;
case HARD :printf("Hard");
break;
case RAM :printf("RAM");
break;
case SUBST :printf("Subst");
break;
case CDROM :printf("CD-ROM");
break;
}
printf("\n");
}
}
}
the asm code is included separately as an ASM file:
; DRIVESEX.ASM - Drive existence detection July 6th, 1994
; Code by : Lee Hamel (hamell@cs.pdx.edu)
; Partial credit: Paul Schlyter
;
; Goes through drives A-Z and determines if they:
; 1) Exist
; 2) Are removable or fixed
; 3) Are local, remote, or shared
; 4) Are a floppy, hard, RAM, subst, or CD-ROM drive
;
; Callable from C as: void Drives_Exist(void);
.model small
.286
DRIVEEXIST EQU 1
REMOVEDRV EQU 0
FIXEDDRV EQU 1
LOCALDRV EQU 0
REMOTEDRV EQU 1
SHAREDRV EQU 2
FLOPPY EQU 0
HARD EQU 1
RAM EQU 2
SUBST EQU 3
CDROM EQU 4
.data
PUBLIC _drives
_drives db 26 dup(0,1,0,1)
; default to not exist, fixed, local, hard drive
.code
PUBLIC _Drives_Exist
_Drives_Exist PROC NEAR
pusha
push es
mov ah,19h
int 21h ; get start drive
push ax ; save start drive
mov ax,40h
mov es,ax
mov bh,es:[10h] ; 40:10h is # of floppies-1
shr bh,6
inc bh ; # of actual floppy drives
mov bl,1
mov di,offset _drives
nextchkfloppy: mov ax,4409h ; check if drive exists
int 21h
jc nextsetfloppy
test dh,10000000b ; check if SUBST drive
jz chkfloppy
dec bh ; dec actual drive count
mov byte ptr [di+3],SUBST
setfloppyexist: mov byte ptr [di],DRIVEEXIST
jmp nextsetfloppy
chkfloppy: dec bh ; dec actual drive count
js nextsetfloppy
mov byte ptr [di+1],REMOVEDRV
mov byte ptr [di+3],FLOPPY
jmp setfloppyexist
nextsetfloppy: add di,4
inc bl
cmp bl,2 ; if B then jump back
je nextchkfloppy
mov ch,24 ; loop 24 times (drives C - Z)
mov cl,3 ; start at C:
drivechkloop: mov ax,4409h ; check if drive exists
mov bl,cl ; set drive letter
int 21h ; 0 = default, 1 = A:, etc.
jc nextsetdrv
mov byte ptr [di],DRIVEEXIST
mov ax,4408h ; check if removable
int 21h
mov byte ptr [di+1],al ; set REMOVABLE or FIXED
mov bx,dx
mov dl,dh
shr dl,7
and dh,00010000b
shr dh,4
mov byte ptr [di+2],dh ; set REMOTE or LOCAL
or dl,dl ; if not SUBST, then jump
jz chkremote
mov byte ptr [di+3],SUBST
jmp nextsetdrv
chkremote: cmp dh,REMOTEDRV ; if REMOTE, then check for CD ROM
je chkcdrom
test bh,00000010b ; sharable?
jz drivenoshare
mov byte ptr [di+2],SHAREDRV
drivenoshare: test bl,00000010b ; RAM drive?
jnz nextsetdrv
mov byte ptr [di+3],RAM
jmp nextsetdrv
chkcdrom: push cx
mov ax,1500h
xor bx,bx
int 2fh
pop cx
or bx,bx ; MSCDEX driver found?
jz nextsetdrv ; if not, jump to next drive setup
mov ax,150bh
dec cl ; 0=A:, etc.
int 2fh
inc cl
or ax,ax
jz nextsetdrv ; drive supported by MSCDEX?
mov byte ptr [di+3],CDROM
nextsetdrv: add di,4
inc cl
dec ch
jnz drivechkloop
pop dx
mov ah,0eh
int 21h ; reset start drive
pop es
popa
ret
_Drives_Exist ENDP
END
Thanks.. i would be grateful to anyone who can answer..
INT 21h is used by MS-DOS programs to do interrupts to MS-DOS (system calls). In 32 bit programs you use Win32 API instead.
Drop INT 21h and replace all int 21h instructions with the proper Win32 function calls.
Also, the 16 bit instructions is probably not a good idea on a 32 bit machine. Yes, most of them can run on a 32 bit machine but they will be slow and clumsy compared to the 32 bit code which is supposed to run on that machine.
Also, isn't it better to use 32 bit registers etc and drop those silly 16 bit registers?
Or use the more inutitive 32 bit adressing modes compared to the silly 16 bit adressing modes.
Writing 32 bit code you can do stuff like:
mov eax,5
mov edx,some_arr[eax*4] // access some_arr[5]
etc etc...
You can use (almost) any register as index register and you can use scaling so that the index register is automatically multiplied by 1, 2, 4 or 8 corresponding to arrays of char, short, int/float or __int64/double.
So drop the 16 bit MASM code and rewrite the thing for Win32. That's my advice.
You CAN use MASM also for 32 bit code, MASM will generate 32 bit code for you, but it is troublesome and not worth the effort, writing C++ or C code and use inline assembly will do it better.
Also, the MASM file you gave really has too much code, you can turn that into C++ code with far fewer lines of code.
Also, the Win32 function to check for drives is much easier to use than the MS-DOS Int 21 interrupt for the same thing. The Win32 function can give you a lot more info and can also give you info on drives that don't have a drive letter. Remember that on newer systems such as WinNT/2000/XP you can have a hard disk or CD-ROM that doesn't have a drive letter. True enough, few people make use of that feature because lots of system software from microsoft isn't able to handle it properly (for example a CD-ROM that doesn't have drive letter won't autoplay, appearantly the autoplay feature bluntly assume that all drives have drive letter for some weird and unknown reason). However, such bugs may some day disappear and then people will start to make use of the fact - especially so when they start to use shared drives and they run out of drive letters to use - after all there are only 26 letters available.
The Win32 functions to ask for drives do not (at least not all of those functions) assume that a drive has a drive letter. They do assume that if you want to access the drive from Win32 that it has a path though, but that is a less strict requirement than that it must have a drive letter.
Welcome to the new world :-)
Alf
Drop INT 21h and replace all int 21h instructions with the proper Win32 function calls.
Also, the 16 bit instructions is probably not a good idea on a 32 bit machine. Yes, most of them can run on a 32 bit machine but they will be slow and clumsy compared to the 32 bit code which is supposed to run on that machine.
Also, isn't it better to use 32 bit registers etc and drop those silly 16 bit registers?
Or use the more inutitive 32 bit adressing modes compared to the silly 16 bit adressing modes.
Writing 32 bit code you can do stuff like:
mov eax,5
mov edx,some_arr[eax*4] // access some_arr[5]
etc etc...
You can use (almost) any register as index register and you can use scaling so that the index register is automatically multiplied by 1, 2, 4 or 8 corresponding to arrays of char, short, int/float or __int64/double.
So drop the 16 bit MASM code and rewrite the thing for Win32. That's my advice.
You CAN use MASM also for 32 bit code, MASM will generate 32 bit code for you, but it is troublesome and not worth the effort, writing C++ or C code and use inline assembly will do it better.
Also, the MASM file you gave really has too much code, you can turn that into C++ code with far fewer lines of code.
Also, the Win32 function to check for drives is much easier to use than the MS-DOS Int 21 interrupt for the same thing. The Win32 function can give you a lot more info and can also give you info on drives that don't have a drive letter. Remember that on newer systems such as WinNT/2000/XP you can have a hard disk or CD-ROM that doesn't have a drive letter. True enough, few people make use of that feature because lots of system software from microsoft isn't able to handle it properly (for example a CD-ROM that doesn't have drive letter won't autoplay, appearantly the autoplay feature bluntly assume that all drives have drive letter for some weird and unknown reason). However, such bugs may some day disappear and then people will start to make use of the fact - especially so when they start to use shared drives and they run out of drive letters to use - after all there are only 26 letters available.
The Win32 functions to ask for drives do not (at least not all of those functions) assume that a drive has a drive letter. They do assume that if you want to access the drive from Win32 that it has a path though, but that is a less strict requirement than that it must have a drive letter.
Welcome to the new world :-)
Alf
ASKER
Thank you for replying neitod and Salte. I've been trying to find some C/C++ codes to help me with this but i didn't think about using Win32 functions to help me..and yeah i'd definitely want to turn all of that MASM code to C++ would you guys know of a good tutorial anywhere to teach a newbie about Win32 API? I've been trying to search all over the net for these kinds of stuff for months.
Again thanks.
Again thanks.
>> Also, the 16 bit instructions is probably not a good idea on a 32 bit machine
That is untrue. don't you think 32 bit programs ever work with bytes and words?
>> You CAN use MASM also for 32 bit code, MASM will generate 32
Unfortunatley, you can't realistically write 32 bit windows program. You can but it is extremely difficult because MS choose to not release the necessary 32 bi t libraries.
>> I've been trying to find some C/C++ codes to help me with this but i didn't
>> think about using Win32 functions to help me
We'll resorting to assembly language seems like an extreme solution!
Its unclear to me what operatiosn you need to perform. But I can assure you that the win32 API provides equivalent operations for every single dos operation (int21) and 1000s more.
I suspect you want to look into functions like
GetDriveType
GetVolumeInformation()
GetLogicalDrives()
GetLogicalDriveStrings()
the additional informaiton under these entries in the VC help will lead you to dozens of more file functions as well
That is untrue. don't you think 32 bit programs ever work with bytes and words?
>> You CAN use MASM also for 32 bit code, MASM will generate 32
Unfortunatley, you can't realistically write 32 bit windows program. You can but it is extremely difficult because MS choose to not release the necessary 32 bi t libraries.
>> I've been trying to find some C/C++ codes to help me with this but i didn't
>> think about using Win32 functions to help me
We'll resorting to assembly language seems like an extreme solution!
Its unclear to me what operatiosn you need to perform. But I can assure you that the win32 API provides equivalent operations for every single dos operation (int21) and 1000s more.
I suspect you want to look into functions like
GetDriveType
GetVolumeInformation()
GetLogicalDrives()
GetLogicalDriveStrings()
the additional informaiton under these entries in the VC help will lead you to dozens of more file functions as well
The Win32 API is probably best documented by Microsoft in the documentation that comes with MSVC and also with Borland C++ builder (yes, it provides microsofts own documentation for the Win32 part).
Just check the help menu or write a function name such as:
CreateFile() or CloseHandle() and you get the help file up, then you can search the index and whatever you want.
Alf
Just check the help menu or write a function name such as:
CreateFile() or CloseHandle() and you get the help file up, then you can search the index and whatever you want.
Alf
actually MASM should work, you just call user32.exe/kernel32.exe/gu i32.exe directly, they are always available to any 32 bit process.
kernel32.exe has the function LoadLibrary which gives you access to any DLL you fancy.
Maybe have a little trouble setting up the interface to call the Win32 functions from those dlls from assembly but it's far from impossible. Essentially you just have to do manually what the C and C++ compilers does for you.
On the other hand, using C++ instead of assembly is far better solution so I think learning the Win32 API as called from C++ and C programs is a far better way to go though.
Alf
kernel32.exe has the function LoadLibrary which gives you access to any DLL you fancy.
Maybe have a little trouble setting up the interface to call the Win32 functions from those dlls from assembly but it's far from impossible. Essentially you just have to do manually what the C and C++ compilers does for you.
On the other hand, using C++ instead of assembly is far better solution so I think learning the Win32 API as called from C++ and C programs is a far better way to go though.
Alf
>> actually MASM should work, you just call user32.exe/kernel32.exe/gu i32.exe directly
Can you imagine writting a "real" program that way? Every Os call would have to be though explicit linking? And how do you call LoadLibrary() and GetProcAddress()? Yes it can be done. I've done it. But its too much work to be worth it. And then consider the fact that you need to define all the OS constants and data structues that you use, because MS didn't release them and becuse h2inc doesn't support win32 stuff.
>> it's far from impossible.
That is why I said its unrealistic.
Can you imagine writting a "real" program that way? Every Os call would have to be though explicit linking? And how do you call LoadLibrary() and GetProcAddress()? Yes it can be done. I've done it. But its too much work to be worth it. And then consider the fact that you need to define all the OS constants and data structues that you use, because MS didn't release them and becuse h2inc doesn't support win32 stuff.
>> it's far from impossible.
That is why I said its unrealistic.
Agree with you, it's not impossible but it is not worth the trouble.
Write C++ or C.
Alf
Write C++ or C.
Alf
ASKER
if you don't mind me asking where did all you guys learn this stuff? but anyway i'll look into this Win32 API calls then i'll get back to you guys.
Thanks
Thanks
ASKER
.. i don't see a tutorial who to use GetLogicalDriveStrings() on MSDN almost all the good tutorials are on Visual Basic, C#..
:(
:(
DWORD StrLen = GetLogicalDriveStrings(0,N
char *DriveString = new char[StrLen + 1]; // Allocate space with room for the NUL.
GetLogicalDriveStrings(Str
delete [] DriveStrings; // clean up.
nietod,
I am watching YOU! You are about 3 questions away from reachin ONE MILLION POINTS!. This is just
* Congratulations! *
in advance!
gonx,
try this... Go to this site:
http://msdn.microsoft.com/default.asp
and in the upper left corner where it says "Search for" type in
GetLogicalDriveStrings
and press Enter. When I did this, the first two items were
1) the official documentation of rhis API function
2) a C++ Q&A article. That article provides a linek to some C++ code for a short program named "ListDrives" (Figure 2).
... a little lower is an overview of Drive-related fns...
5. http://msdn.microsoft.com/library/en-us/fileio/base/volume_management_functions.asp
That is how to locate information about Win32 API functions.
-- Dan
I am watching YOU! You are about 3 questions away from reachin ONE MILLION POINTS!. This is just
* Congratulations! *
in advance!
gonx,
try this... Go to this site:
http://msdn.microsoft.com/default.asp
and in the upper left corner where it says "Search for" type in
GetLogicalDriveStrings
and press Enter. When I did this, the first two items were
1) the official documentation of rhis API function
2) a C++ Q&A article. That article provides a linek to some C++ code for a short program named "ListDrives" (Figure 2).
... a little lower is an overview of Drive-related fns...
5. http://msdn.microsoft.com/library/en-us/fileio/base/volume_management_functions.asp
That is how to locate information about Win32 API functions.
-- Dan
ASKER
i already went to the links Dan wrote so im now fixing up the source of ListDrives.. i hope to understand why its giving me a
LINK : fatal error LNK1117: syntax error in option "subsystem:ListDrives"
neitod, the code definitely looks simpler than the MFC code from MSDN. Ive seen some code like that from the other threads here but for the life of me i have to study the whole thing all over again.. do you have a complete listing of the snippet?
LINK : fatal error LNK1117: syntax error in option "subsystem:ListDrives"
neitod, the code definitely looks simpler than the MFC code from MSDN. Ive seen some code like that from the other threads here but for the life of me i have to study the whole thing all over again.. do you have a complete listing of the snippet?
>> am watching YOU! You are about 3 questions away from reachin ONE MILLION POINTS!.
I thought it was like 600,000???
try a console program with
#include <windows.h>
#include <iostream>
using namespace std;
int main()
{
DWORD StrLen = GetLogicalDriveStrings(0,N ULL); // Find necessary length.
char *DriveString = new char[StrLen + 1]; // Allocate space with room for the NUL.
GetLogicalDriveStrings(Str Len,DriveS tring) // Get the string.
cout << DriveString << endl;
delete [] DriveString; // clean up.
return 0;
}
I thought it was like 600,000???
try a console program with
#include <windows.h>
#include <iostream>
using namespace std;
int main()
{
DWORD StrLen = GetLogicalDriveStrings(0,N
char *DriveString = new char[StrLen + 1]; // Allocate space with room for the NUL.
GetLogicalDriveStrings(Str
cout << DriveString << endl;
delete [] DriveString; // clean up.
return 0;
}
ASKER
neitod or anyone for that matter, just this last question then my points are yours..
how do you loop the program so it detects every drive?
TY.
how do you loop the program so it detects every drive?
TY.
The function returns ALL the drives. You just have to extract them. I can post a little _sample_ code.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
>> thought it was like 600,000???
You have over 850,000 in C++ alone (you are the top expert in this TA) and another 145,000 in Windows Programming TA (you are #5 there). Current total: 995,314
-- Dan
You have over 850,000 in C++ alone (you are the top expert in this TA) and another 145,000 in Windows Programming TA (you are #5 there). Current total: 995,314
-- Dan
ASKER
You guys could write a good book/tutorials on these things
Why do you want to use assembly anyways? Why not just handle it all in C++?
>> ive been trying to understand why the msdev hangs when it reaches INT 21h
because that itnterrupt is for 16 bit programs.