I'm just messing around here trying to learn how some of this low level
stuff works, and to my surprise I can not find a working example any
where...
Can someone please help. I'm about to pull my hair out!
I'm using visual studio 1.52 to compile my 16 bit code. I'm doing C
with inline ASM.
Note: I called check_extensions and extension are on my computer.
When i compile and run the following code bError prints out "0" so that
is no error i think? Yet when i print out my buffer the buffer is all
0's which i know is wrong because i have another functions that read
the MBR in with CHS format call and then it prints out the mbr just
fine. Any ideas?
struct disk_packet //needed for int13 42h
{
BYTE size_pack; //size of packet must be 16 or 16+
BYTE reserved1; //reserved
BYTE no_of_blocks; //no:of blocks for transfer
BYTE reserved2; //reserved
WORD offset; //offset address
WORD segment; //segment address
DWORD lba1;
DWORD lba2;
} disk_pack;
void LBASectorRead(void *buffer, unsigned long lba )
{
unsigned char bError = 0;
disk_pack.size_pack=16; //set size to 16
disk_pack.no_of_blocks=1; //1 block ie read one sector
disk_pack.reserved1=0; //reserved word
disk_pack.reserved2=0; //reserved word
disk_pack.segment=FP_SEG(buffer); //segment of buffer
disk_pack.offset=FP_OFF(buffer); //offset of buffer
disk_pack.lba1=0; //lba first 32 bits
disk_pack.lba2=0; //last 32 bit address
_asm
{
mov dl, 80h;
mov [disk_pack.segment], ds;
mov si, disk_pack;
mov ah, 42h;
int 13h
jc NoError ; //No error, ignore error code
mov bError, ah ; // Error, get the error code
NoError:
}
printf( "%d", bError);
}
int main(void)
{
static unsigned char currentMBR[SECTOR_SIZE] = {0};
printf("\n\n");
LBASectorRead(currentMBR );
PrintSector(currentMBR); //function to print buffer in hex
}
|
|
0
|
|
|
|
Reply
|
spamtrap2 (1628)
|
10/5/2006 6:56:05 PM |
|
On 5 Oct 2006 11:56:05 -0700, "jay" <spamtrap@crayne.org> wrote:
>I'm just messing around here trying to learn how some of this low level
>stuff works, and to my surprise I can not find a working example any
>where...
>
>Can someone please help. I'm about to pull my hair out!
>I'm using visual studio 1.52 to compile my 16 bit code. I'm doing C
>with inline ASM.
>Note: I called check_extensions and extension are on my computer.
>
>When i compile and run the following code bError prints out "0" so that
>is no error i think? Yet when i print out my buffer the buffer is all
>0's which i know is wrong because i have another functions that read
>the MBR in with CHS format call and then it prints out the mbr just
>fine. Any ideas?
>
>
>struct disk_packet //needed for int13 42h
>{
> BYTE size_pack; //size of packet must be 16 or 16+
> BYTE reserved1; //reserved
> BYTE no_of_blocks; //no:of blocks for transfer
> BYTE reserved2; //reserved
> WORD offset; //offset address
> WORD segment; //segment address
> DWORD lba1;
> DWORD lba2;
>} disk_pack;
>
>void LBASectorRead(void *buffer, unsigned long lba )
>{
> unsigned char bError = 0;
> disk_pack.size_pack=16; //set size to 16
> disk_pack.no_of_blocks=1; //1 block ie read one sector
> disk_pack.reserved1=0; //reserved word
> disk_pack.reserved2=0; //reserved word
> disk_pack.segment=FP_SEG(buffer); //segment of buffer
> disk_pack.offset=FP_OFF(buffer); //offset of buffer
> disk_pack.lba1=0; //lba first 32 bits
> disk_pack.lba2=0; //last 32 bit address
>
> _asm
> {
> mov dl, 80h;
> mov [disk_pack.segment], ds;
mov ds, [disk_pack.segment]; // I think
though wouldn't this use the same FP_??? as in the packet?
> mov si, disk_pack;
> mov ah, 42h;
> int 13h
> jc NoError ; //No error, ignore error code
> mov bError, ah ; // Error, get the error code
> NoError:
> }
>
> printf( "%d", bError);
>
>}
>
>int main(void)
>{
> static unsigned char currentMBR[SECTOR_SIZE] = {0};
> printf("\n\n");
> LBASectorRead(currentMBR );
> PrintSector(currentMBR); //function to print buffer in hex
>}
--
Doors - Dont look at the future in a window.
Walk to a door - Open it, and go there.
http://www.freedoors.org
doorsremove@mefreedoors.org
mailto:doorsremove@mefreedoors.org
|
|
0
|
|
|
|
Reply
|
Doors
|
10/6/2006 6:54:08 AM
|
|
I tried messing around with the line of code that you suggested but now
the programs just hangs.
Can anyone help me fix up this code. I really need to find a working
example of LBA_Read_Sector or I would prefer even more to just make
this block of code work correctly. I'm not really an assembley expert.
Jay
|
|
0
|
|
|
|
Reply
|
jay
|
10/11/2006 3:41:47 PM
|
|
jay wrote:
> I'm just messing around here trying to learn how some of this low level
> stuff works, and to my surprise I can not find a working example any
> where...
>
> Can someone please help. I'm about to pull my hair out!
> I'm using visual studio 1.52 to compile my 16 bit code. I'm doing C
> with inline ASM.
> Note: I called check_extensions and extension are on my computer.
>
> When i compile and run the following code bError prints out "0" so that
> is no error i think? Yet when i print out my buffer the buffer is all
> 0's which i know is wrong because i have another functions that read
> the MBR in with CHS format call and then it prints out the mbr just
> fine. Any ideas?
>
>
> struct disk_packet //needed for int13 42h
> {
> BYTE size_pack; //size of packet must be 16 or 16+
> BYTE reserved1; //reserved
> BYTE no_of_blocks; //no:of blocks for transfer
> BYTE reserved2; //reserved
> WORD offset; //offset address
> WORD segment; //segment address
> DWORD lba1;
> DWORD lba2;
> } disk_pack;
>
> void LBASectorRead(void *buffer, unsigned long lba )
> {
> unsigned char bError = 0;
> disk_pack.size_pack=16; //set size to 16
> disk_pack.no_of_blocks=1; //1 block ie read one sector
> disk_pack.reserved1=0; //reserved word
> disk_pack.reserved2=0; //reserved word
> disk_pack.segment=FP_SEG(buffer); //segment of buffer
> disk_pack.offset=FP_OFF(buffer); //offset of buffer
> disk_pack.lba1=0; //lba first 32 bits
> disk_pack.lba2=0; //last 32 bit address
>
> _asm
> {
> mov dl, 80h;
> mov [disk_pack.segment], ds;
> mov si, disk_pack;
I'm not familiar with the syntax you're using... Should this be "offset
disk_pack"?
Best,
Frank
|
|
0
|
|
|
|
Reply
|
Frank
|
10/11/2006 7:18:37 PM
|
|
I have no idea about the format. I'm not sure what offset I want. I
copied this code from another posting in google groups from someone who
"Claimed" this code worked to do a read sector with an LBA address.
Only when I compile and run the code and display (ie print out ) my
read sector it is all 00's so I know it didnt work.
|
|
0
|
|
|
|
Reply
|
jay
|
10/11/2006 8:09:35 PM
|
|
jay wrote:
> I tried messing around with the line of code that you suggested but now
> the programs just hangs.
>
> Can anyone help me fix up this code. I really need to find a working
> example of LBA_Read_Sector or I would prefer even more to just make
> this block of code work correctly. I'm not really an assembley expert.
I just happened to update an old disk erasure program yesterday, it is
written in Turbo Pascal with inline asm for all the lowlevel stuff.
If you send me an email, I'll send you the source code.
OK?
Terje
--
- <Terje.Mathisen@hda.hydro.com>
"almost all programming can be viewed as an exercise in caching"
|
|
0
|
|
|
|
Reply
|
Terje
|
10/11/2006 8:40:47 PM
|
|
"jay" <spamtrap@crayne.org> wrote in message
news:1160074565.866424.132440@m7g2000cwm.googlegroups.com...
> I'm just messing around here trying to learn how some of this low level
> stuff works, and to my surprise I can not find a working example any
> where...
>
<snip>
(on comp.lang.asm.x86 and a similar post on alt.os.development "Read Sector
(LBA mode)")
You could look at LFN tools by Ortwin "Odi" Glueck. In addition to working
for Real Mode DOS, they implement Windows drive locking, and should work for
Protected Mode "DOS-boxes" and DOS emulators under older Windows OS:
Win95/98/98SE/ME etc. I don't know whether the drive locking will work
under Protected Mode "DOS-boxes" and DOS emulators for 2k/NT/XP. The source
code is for Microsoft Visual C++ 1.51.
http://lfntools.sourceforge.net/
http://www.odi.ch/prog/lfn/index.php
Also, Chris Giese wrote a LBA routine originally for DJGPP:
http://my.execpc.com/CE/AC/geezer/software/djgpplba.c
I ported it to OpenWatcom. This link has it in html form with useful
comments.
http://www.openwatcom.org/index.php/Accessing_the_Harddisk_using_LBA_under_DPMI
These links have "my" complete ported source without html.
http://groups.google.com/group/openwatcom.users.c_cpp/msg/91921e7bfb09bcbc?hl=en
http://groups.google.com/group/openwatcom.users.c_cpp/msg/dd21a94062d38ad8?hl=en
Chris also ported it at a later date to OpenWatcom using a slightly
different technique:
http://my.execpc.com/CE/AC/geezer/temp/djdisk.c
<snip, problems...>
> Any ideas?
>
Let me take a look...
> struct disk_packet //needed for int13 42h
> {
> BYTE size_pack; //size of packet must be 16 or 16+
> BYTE reserved1; //reserved
> BYTE no_of_blocks; //no:of blocks for transfer
> BYTE reserved2; //reserved
> WORD offset; //offset address
> WORD segment; //segment address
> DWORD lba1;
> DWORD lba2;
> } disk_pack;
>
The first problem is that it appears that your struct isn't packed. This
means that additional bytes, which are used to align the structure, might be
inserted by the compiler. Of course, DOS doesn't recognized those inserted
bytes... You'll need to look for a compiler specific option, something like
"#pragma pack","__attribute__((packed))","_Packed", etc.
(Since I'm experiencing major "Deja Vu," after reading the rest of this
post, you might view this similar thread w/Ernesto a while back on
alt.os.development)
http://groups.google.com/group/alt.os.development/browse_frm/thread/c80d83d660e2b760/86d328a4777de8ef?&hl=en#86d328a4777de8ef
Second, I don't think this is an issue, but it might be. You are using two
32-bit lba fields instead of one 64-bit field.
Third, you've also obfuscated the "BYTE", "WORD", "DWORD", etc. BYTE should
be an unsigned 8-bit quantity. The others should also be unsigned of the
exact bit size. You probably have some defines like so:
#define BYTE unsigned char
#define WORD unsigned shor
#define DWORD unsigned long
#define QWORD unsigned long long
You might try using "uint8_t", "uint16_t", "uint32_t", and "uint64_t" if
your compiler has C99's stdint.h.
> void LBASectorRead(void *buffer, unsigned long lba )
> {
> unsigned char bError = 0;
> disk_pack.size_pack=16; //set size to 16
> disk_pack.no_of_blocks=1; //1 block ie read one sector
> disk_pack.reserved1=0; //reserved word
> disk_pack.reserved2=0; //reserved word
> disk_pack.segment=FP_SEG(buffer); //segment of buffer
> disk_pack.offset=FP_OFF(buffer); //offset of buffer
> disk_pack.lba1=0; //lba first 32 bits
> disk_pack.lba2=0; //last 32 bit address
>
> _asm
> {
> mov dl, 80h;
> mov [disk_pack.segment], ds;
> mov si, disk_pack;
> mov ah, 42h;
> int 13h
> jc NoError ; //No error, ignore error code
> mov bError, ah ; // Error, get the error code
> NoError:
> }
>
First, it appears that this line is reversed. I think you should be setting
ds instead of saving it:
> mov [disk_pack.segment], ds;
mov ds,[disk_pack.segment]
Second, IIRC, LBA block numbering starts at 1 (one), but it appears that
both lba1 and lba2 are zero.
Third, you first need to check if the BIOS supports ah=42h by calling
ah=41h,bx=55AA. I suggest you obtain a copy of Ralph Brown's interrupt list
if you don't have it.
Fourth, since you didn't pack your struct, "disk_pack.size_pack" might not
be 16, although it should be.
> disk_pack.size_pack=16;
disk_pack.size_pack=sizeof(disk_pack); /* this should be 16, if correctly
packed */
Fourth, it won't work under Windows since there is no drive locking.
Five, if you're compiling for DPMI or a Dos Extender (both PM 32-bit), your
"buffer" variable and "disk_packet" struct may be above 1Mb. Both will need
to be copied from a virtual address above 1Mb to a physical Real Mode
address below 1Mb to be accessed by DOS and BIOS. Of course, the reverse
must be done upon completion.
Sixth, your compiler may have C structures which map to the registers. It
might be easier to use them.
Rod Pemberton
|
|
0
|
|
|
|
Reply
|
Rod
|
10/13/2006 8:03:38 AM
|
|
updated my code and tried several different thing but still nothing
works. I have a functions that checks for extensions and my machine has
the extensions. It is a fairly new dell inspiron 8500. Using visual
studio to make a DOS exe program. I did NOT select P-mode DOS so I
guess that means i'm working in real mode. I know the PrintSector
function works fine because if try a not extended (ie read int 13 ah=2)
then the whole thing works fine (but of course i want to have an
extended read function)
here is the code:
typedef unsigned char BYTE;
typedef unsigned short WORD;
typedef unsigned long DWORD;
typedef struct {
unsigned long low;
unsigned long high;
} QDWORD;
void PrintSector ( void * );
void LBASectorRead(void *, double );
int check_ext_present();
QDWORD double2qd( double x )
{
QDWORD qdw;
qdw.high = (unsigned long)(x/4294967296.0);
qdw.low = (unsigned long) x;
return qdw;
}
#pragma pack(1)
typedef struct disk_packet
{
BYTE size_pack; //size of packet must be 16 or 16+
BYTE reserved1; //reserved
BYTE no_of_blocks; //no:of blocks for transfer
BYTE reserved2; //reserved
DWORD TransAddr; //address in seg:off format
QDWORD lba; //quad word sector to read
};
struct disk_packet disk_pack;
void LBASectorRead(void *buffer, double lba )
{
union REGS uRegs;
struct SREGS sSeg;
disk_pack.TransAddr = 0;
disk_pack.size_pack=sizeof(disk_pack); //set size to 16
disk_pack.no_of_blocks=1; //1 block
disk_pack.reserved1=0x0;
disk_pack.reserved2=0x0;
disk_pack.TransAddr = (unsigned long) MK_FP( FP_SEG(buffer),
FP_OFF(buffer));
disk_pack.lba=double2qd( lba );
sSeg.ds = FP_SEG( disk_pack );
uRegs.x.si = FP_OFF( disk_pack );
uRegs.h.dl = 0x80;
uRegs.h.ah = 0x42;
int86x( 0x13, &uRegs, &uRegs, &sSeg);
printf("\n\nError: %x", uRegs.x.cx );
}
void Main ( void )
{
static unsigned char currentMBR[512] = {0};
LBASectorRead(currentMBR, 1 );
PrintSector ( currentMBR );
}
|
|
0
|
|
|
|
Reply
|
jay
|
10/26/2006 5:39:35 PM
|
|
"jay" <spamtrap@crayne.org> wrote in message
news:1161884374.929492.285360@k70g2000cwa.googlegroups.com...
> updated my code and tried several different thing but still nothing
> works. I have a functions that checks for extensions and my machine has
> the extensions. It is a fairly new dell inspiron 8500. Using visual
> studio to make a DOS exe program. I did NOT select P-mode DOS so I
> guess that means i'm working in real mode. I know the PrintSector
> function works fine because if try a not extended (ie read int 13 ah=2)
> then the whole thing works fine (but of course i want to have an
> extended read function)
>
> here is the code:
>
The MSVC 1.52 code looked similar to OpenWatcom. So, I decided to try it.
The code runs with a few minor changes for OW. Sorry, it appears that I was
the culprit behind one of them being incorrect. I also found a few
additional issues. First, here's the code changes:
> typedef unsigned char BYTE;
> typedef unsigned short WORD;
> typedef unsigned long DWORD;
>
> typedef struct {
> unsigned long low;
> unsigned long high;
> } QDWORD;
>
> void PrintSector ( void * );
> void LBASectorRead(void *, double );
> int check_ext_present();
>
> QDWORD double2qd( double x )
> {
> QDWORD qdw;
> qdw.high = (unsigned long)(x/4294967296.0);
> qdw.low = (unsigned long) x;
> return qdw;
> }
>
> #pragma pack(1)
> typedef struct disk_packet
> {
> BYTE size_pack; //size of packet must be 16 or 16+
> BYTE reserved1; //reserved
> BYTE no_of_blocks; //no:of blocks for transfer
> BYTE reserved2; //reserved
> DWORD TransAddr; //address in seg:off format
> QDWORD lba; //quad word sector to read
> };
> struct disk_packet disk_pack;
>
> void LBASectorRead(void *buffer, double lba )
> {
> union REGS uRegs;
> struct SREGS sSeg;
>
> disk_pack.TransAddr = 0;
> disk_pack.size_pack=sizeof(disk_pack); //set size to 16
> disk_pack.no_of_blocks=1; //1 block
> disk_pack.reserved1=0x0;
> disk_pack.reserved2=0x0;
> disk_pack.TransAddr = (unsigned long) MK_FP( FP_SEG(buffer),
> FP_OFF(buffer));
> disk_pack.lba=double2qd( lba );
>
> sSeg.ds = FP_SEG( disk_pack );
> uRegs.x.si = FP_OFF( disk_pack );
sSeg.ds = FP_SEG( &disk_pack );
uRegs.x.si = FP_OFF( &disk_pack );
>
> uRegs.h.dl = 0x80;
> uRegs.h.ah = 0x42;
>
> int86x( 0x13, &uRegs, &uRegs, &sSeg);
>
> printf("\n\nError: %x", uRegs.x.cx );
printf("CF: %x", uRegs.x.cflag );
printf("AX: %x\n", uRegs.x.ax );
> }
>
>
> void Main ( void )
int main(void)
( Lowercase! This was a "nice" error. It totally hosed 16-bit OW. )
> {
> static unsigned char currentMBR[512] = {0};
>
> LBASectorRead(currentMBR, 1 );
LBASectorRead(currentMBR, 0 );
LBA sector numbers start at 1, but the appears that int 0x13 interface uses
LBA-1. Again, sorry. I'm not sure where this is documented. I didn't see
in Ralph Brown's interrupt list. It might be in the ATAPI specs or the
ancient Phoenix EDD specs somewhere.
> PrintSector ( currentMBR );
> }
>
After making those changes (and adding my own PrintSector, and
check_ext_present), it compiled for OW and loaded the correct track (under
RM DOS). In addition to stdio.h and stdlib.h, I included OW's i86.h, but I
believe MSVC uses dos.h or bios.h.
The first issue is that although you typedef'd BYTE, WORD, etc. You didn't
use them throughout the code. Take a look at your QDWORD struct and your
(unsigned long) casts.
Second, OW represents 16-bit addresses in segment:offset form. This may
also be the case for MSVC 1.52. In which case, the following change will
work:
> disk_pack.TransAddr=(unsigned long)MK_FP(FP_SEG(buffer),FP_OFF(buffer));
disk_pack.TransAddr=(unsigned long)buffer;
Third, the disk_packet struct is defined differently in Chris Giese's code
versus Ralph Brown's interrupt list. I didn't notice this previously. CG
defines it like so (in his code, those are typedef's like yours, not C99
stdint.h):
uint8_t packet_len;
uint8_t reserved1;
uint8_t nsects;
uint8_t reserved2;
uint16_t buf_offset;
uint16_t buf_segment;
uint64_t lba;
But, Ralph Brown's interrupt had it like this (with an optional QWORD, for
EDD 3.0):
00h BYTE size of packet (10h or 18h)
01h BYTE reserved (0)
02h WORD number of blocks to transfer (max 007Fh for Phoenix EDD)
04h DWORD -> transfer buffer
08h QWORD starting absolute block number
10h QWORD (EDD-3.0, optional) 64-bit flat address of transfer buffer; used
if DWORD at 04h is FFFFh:FFFFh
RB's would make your no_of_blocks a WORD and eliminate reserved2. RB
indicates the reserved2 would always be 0 for Phoenix EDD, but the
no_of_blocks was obviously defined with room for a larger value.
>I did NOT select P-mode DOS so I
> guess that means i'm working in real mode.
Sorry, no. It means you created a real mode DOS application, but you could
be attempting to run it in a protected mode emulator or the x86 CPU's V86
mode, usually called a DOS-box. If you're running the code from Windows
3.1/98/98SE/98ME/NT/2k/XP, Linux, Bochs, VMWare, QEMU, DOSBox, DOSEMU, etc.,
don't expect the code to work. Windows3.1/98/98SE/98ME were built on top of
MS-DOS, so it is possible to boot directly into RM DOS instead of Windows
with those OS's. Win98ME requires a patch to boot RM DOS. If you're
running from Windows, you'll need to add additional file/drive locking code
to work under Windows.
Rod Pemberton
|
|
0
|
|
|
|
Reply
|
Rod
|
10/27/2006 4:04:53 AM
|
|
> > sSeg.ds = FP_SEG( disk_pack );
> > uRegs.x.si = FP_OFF( disk_pack );
>
> sSeg.ds = FP_SEG( &disk_pack );
> uRegs.x.si = FP_OFF( &disk_pack );
I have tried it both ways. Everything I have been seeing indicates that
i should have the & present but visual studio give me an error " '&'
requires l-value " and the only way to get ride of the error is to
remove the & from the code?? any ideas on this?
> > disk_pack.TransAddr=(unsigned long)MK_FP(FP_SEG(buffer),FP_OFF(buffer));
> disk_pack.TransAddr=(unsigned long)buffer;
I made this change and that make sense. That seems okee.
I changed my structure to match this
> 00h BYTE size of packet (10h or 18h)
> 01h BYTE reserved (0)
> 02h WORD number of blocks to transfer (max 007Fh for Phoenix EDD)
> 04h DWORD -> transfer buffer
> 08h QWORD starting absolute block number
> 10h QWORD (EDD-3.0, optional) 64-bit flat address of transfer buffer; used
> if DWORD at 04h is FFFFh:FFFFh
> Sorry, no. It means you created a real mode DOS application, but you could
> be attempting to run it in a protected mode emulator or the x86 CPU's V86
> mode, usually called a DOS-box. If you're running the code from Windows
> 3.1/98/98SE/98ME/NT/2k/XP, Linux, Bochs, VMWare, QEMU, DOSBox, DOSEMU, etc.,
> don't expect the code to work. Windows3.1/98/98SE/98ME were built on top of
> MS-DOS, so it is possible to boot directly into RM DOS instead of Windows
> with those OS's. Win98ME requires a patch to boot RM DOS. If you're
> running from Windows, you'll need to add additional file/drive locking code
> to work under Windows.
>
I'm compiling the code and coping to a bootable DOS floopy disk and
then restarting my computer. This makes testing a HUGE pain so needless
to say I would like to resolve this soon.
Thanks again.
jay
|
|
0
|
|
|
|
Reply
|
jay
|
10/30/2006 5:38:36 PM
|
|
On Tue, 31 Oct 2006 04:38:36 +1100, jay <spamtrap@crayne.org> wrote:
>> > sSeg.ds = FP_SEG( disk_pack );
>> > uRegs.x.si = FP_OFF( disk_pack );
>>
>> sSeg.ds = FP_SEG( &disk_pack );
>> uRegs.x.si = FP_OFF( &disk_pack );
>
> I have tried it both ways. Everything I have been seeing indicates that
> i should have the & present but visual studio give me an error " '&'
> requires l-value " and the only way to get ride of the error is to
> remove the & from the code?? any ideas on this?
Well there's nothing wrong your software development technique. Just keep
changing the code at random until it seems to work :-)
Nah, but seriously, though... in Microsoft C up to v7 and Visual C++ up to
v1.5 (for real-mode) FP_OFF and FP_SEG require that you pass a pointer to
them. Passing an address won't cut the mustard, even though on the face of
it it's the same thing. The reason is that these macros dereference the
pointer - something that can't be done to an address. Check out the
ancient MSDN article Q47497, dated 1997, if you can find it.
The solution/workaround (I'm not really sure how to characterize it) is to
define a pointer variable that points to disk_pack and then pass that to
the macros:
struct disk_packet *p = &disk_pack;
blah = FP_SEG(p);
I haven't taken the time to make sure I've got it exactly right, and I
haven't been paying attention to what the code is really trying to do, but
that should be enough to get you on the right track.
Cheers,
Ciaran
--
Ciaran Keating
Amad�n Technologies Pty Ltd
|
|
0
|
|
|
|
Reply
|
Ciaran
|
10/31/2006 12:55:21 AM
|
|
"Ciaran Keating" <spamtrap@crayne.org> wrote in message
news:op.th9gv6pblndgv1@elmo...
> On Tue, 31 Oct 2006 04:38:36 +1100, jay <spamtrap@crayne.org> wrote:
>
> >> > sSeg.ds = FP_SEG( disk_pack );
> >> > uRegs.x.si = FP_OFF( disk_pack );
> >>
> >> sSeg.ds = FP_SEG( &disk_pack );
> >> uRegs.x.si = FP_OFF( &disk_pack );
> >
> > I have tried it both ways. Everything I have been seeing indicates that
> > i should have the & present but visual studio give me an error " '&'
> > requires l-value " and the only way to get ride of the error is to
> > remove the & from the code?? any ideas on this?
>
> Well there's nothing wrong your software development technique. Just keep
> changing the code at random until it seems to work :-)
>
> Nah, but seriously, though... in Microsoft C up to v7 and Visual C++ up to
> v1.5 (for real-mode) FP_OFF and FP_SEG require that you pass a pointer to
> them. Passing an address won't cut the mustard, even though on the face of
> it it's the same thing. The reason is that these macros dereference the
> pointer - something that can't be done to an address. Check out the
> ancient MSDN article Q47497, dated 1997, if you can find it.
>
> The solution/workaround (I'm not really sure how to characterize it) is to
> define a pointer variable that points to disk_pack and then pass that to
> the macros:
>
> struct disk_packet *p = &disk_pack;
> blah = FP_SEG(p);
Although your solution seems fine, if that still doesn't work, he might try:
unsigned __far *p;
p = (unsigned __far *)&disk_pack;
blah = FP_SEG(p);
Also, you stated:
> The reason is that these macros dereference the
> pointer - something that can't be done to an address.
I think that part of your explanation is inaccurate. I believe this is from
the same compiler he's using:
>From "errata":
"_FP_OFF, _FP_SEG
Add the following note to the Remarks section.
The argument to _FP_OFF and _FP_SEG must be a far pointer variable. It
cannot be an array name, or a near pointer cast to a far pointer."
It appears, from _FP_SEG/OFF in dos.h, that their use of the address
operator within the macro definitions is the primary cause of the problem:
#define _FP_SEG(fp) (*((unsigned __far *)&(fp)+1))
#define _FP_OFF(fp) (*((unsigned __far *)&(fp)))
A secondary issue is their assumption of a "far pointer" format or perhaps
they have casting conversion failure. I'd presume, without knowing as fact,
that the address operator, &, returns a "near pointer" for VC which is
probably the reason why taking the address of the struct in the OP's
original code might not or didn't work.
Rod Pemberton
|
|
0
|
|
|
|
Reply
|
Rod
|
11/1/2006 12:57:16 AM
|
|
Hi Rod,
On Wed, 01 Nov 2006 11:57:16 +1100, Rod Pemberton <spamtrap@crayne.org>
wrote:
>> struct disk_packet *p = &disk_pack;
>> blah = FP_SEG(p);
>
> Although your solution seems fine, if that still doesn't work, he might
> try:
>
> unsigned __far *p;
> p = (unsigned __far *)&disk_pack;
> blah = FP_SEG(p);
Not trying to pick a fight here, but this looks like more of jay's hopeful
bit-fiddling. I can't see how this is any different - all you've done is
changed the target type of the pointer, you haven't changed any of the
qualities of the pointer itself. Particularly in C, with its type-unsafety
(is that a word?) this is a no-op. Even in C++ (although the code smacks
of C) this casting might affect syntax, but not semantics.
> I think that part of your explanation is inaccurate. I believe this is
> from
> the same compiler he's using:
Perhaps. My information came from a very old MSDN disk, although it did
say explicitly that it applied to the following products:
- Microsoft C for MS-DOS, versions 5.1, 6.0, 6.0a, and 6.0ax
- Microsoft C for OS/2, versions 5.1, 6.0, and 6.0a
- Microsoft C/C++ for MS-DOS, version 7.0
- Microsoft Visual C++ for Windows, versions 1.0 and 1.5
And this article explicitly says that passing the address of something,
rather than an actual pointer to it, will give the error that jay
encountered.
> The argument to _FP_OFF and _FP_SEG must be a far pointer variable. It
> cannot be an array name, or a near pointer cast to a far pointer."
I imagine the reason it can't be a near pointer cast to a far pointer is
not because of some shortcoming in the implementation of FP_SEG/FP_OFF.
(Not sure why your documentation gives a leading underscore...?) The
reason you can't just cast a short pointer to a long pointer is that the
result will simply be incorrect - the cast can't synthesize the segment
information, but just sign-extends the short part. Or something like that.
And I could be wrong, of course.
> It appears, from _FP_SEG/OFF in dos.h, that their use of the address
> operator within the macro definitions is the primary cause of the
> problem:
>
> #define _FP_SEG(fp) (*((unsigned __far *)&(fp)+1))
> #define _FP_OFF(fp) (*((unsigned __far *)&(fp)))
Don't know what you see wrong here, and I'm too hungry right now to worry
about it :-)
> A secondary issue is their assumption of a "far pointer" format or
> perhaps
> they have casting conversion failure. I'd presume, without knowing as
> fact,
> that the address operator, &, returns a "near pointer" for VC which is
> probably the reason why taking the address of the struct in the OP's
> original code might not or didn't work.
Hmm... it's a hundred years since I did any real-mode programming, but if
you select the correct memory model then surely &blah will yield the
correct size of pointer?
Anyway, jay, if you're still here then let us know how you get on.
Cheers,
Ciaran
--
Ciaran Keating
Amad�n Technologies Pty Ltd
|
|
0
|
|
|
|
Reply
|
Ciaran
|
11/1/2006 3:47:09 AM
|
|
If you are so totally lost, I have some source for a disk wiper
utility that uses MSC 1.52c. It uses standard INT 13h and the
extended functions when supported. It was written before the extended
functions and updated when they appeared. Provide me with an email
address, such as: delta alpha victor echo at yankee oscar sierra hotel
india mike uniform nancy india dot charlie oscar mike, which is mine.
On 30 Oct 2006 09:38:36 -0800, "jay" <spamtrap@crayne.org> wrote:
>> > sSeg.ds = FP_SEG( disk_pack );
>> > uRegs.x.si = FP_OFF( disk_pack );
>>
>> sSeg.ds = FP_SEG( &disk_pack );
>> uRegs.x.si = FP_OFF( &disk_pack );
>
>I have tried it both ways. Everything I have been seeing indicates that
>i should have the & present but visual studio give me an error " '&'
>requires l-value " and the only way to get ride of the error is to
>remove the & from the code?? any ideas on this?
>
>> > disk_pack.TransAddr=(unsigned long)MK_FP(FP_SEG(buffer),FP_OFF(buffer));
>> disk_pack.TransAddr=(unsigned long)buffer;
>
>I made this change and that make sense. That seems okee.
>
>
>I changed my structure to match this
>
>> 00h BYTE size of packet (10h or 18h)
>> 01h BYTE reserved (0)
>> 02h WORD number of blocks to transfer (max 007Fh for Phoenix EDD)
>> 04h DWORD -> transfer buffer
>> 08h QWORD starting absolute block number
>> 10h QWORD (EDD-3.0, optional) 64-bit flat address of transfer buffer; used
>> if DWORD at 04h is FFFFh:FFFFh
>
>
>
>> Sorry, no. It means you created a real mode DOS application, but you could
>> be attempting to run it in a protected mode emulator or the x86 CPU's V86
>> mode, usually called a DOS-box. If you're running the code from Windows
>> 3.1/98/98SE/98ME/NT/2k/XP, Linux, Bochs, VMWare, QEMU, DOSBox, DOSEMU, etc.,
>> don't expect the code to work. Windows3.1/98/98SE/98ME were built on top of
>> MS-DOS, so it is possible to boot directly into RM DOS instead of Windows
>> with those OS's. Win98ME requires a patch to boot RM DOS. If you're
>> running from Windows, you'll need to add additional file/drive locking code
>> to work under Windows.
>>
>
>I'm compiling the code and coping to a bootable DOS floopy disk and
>then restarting my computer. This makes testing a HUGE pain so needless
>to say I would like to resolve this soon.
>
>Thanks again.
>jay
|
|
0
|
|
|
|
Reply
|
spamtrap
|
11/1/2006 4:14:41 AM
|
|
|
13 Replies
574 Views
(page loaded in 0.139 seconds)
Similiar Articles: LSA Disk Sector Read - using int 13h ah 42 (extended read) - comp ...I'm just messing around here trying to learn how some of this low level stuff works, and to my surprise I can not find a working example any where... ... ntvdm encountered a hard error - comp.lang.asm.x86As I said to Jay in one of the posts in "LSA Disk Sector Read - using int 13h ah 42 (extended read ... READ,FILE_SHARE_WRITE,0,OPEN_EXISTING,0,0 ;Just reading, not ... how to get some values for LBA <-> CHS conversion? - comp.lang.asm ...LSA Disk Sector Read - using int 13h ah 42 (extended read) - comp ..... messing around here trying to learn how some ... give me an error " '&' >requires l-value " and ... Re: is there an easy way to call int 10h on Windows XP? - comp ...LSA Disk Sector Read - using int 13h ah 42 (extended read) - comp ... Re: is there an easy way to call int 10h on Windows XP? - comp ... LSA Disk Sector Read - using int ... Acer Apire 3000 keyboard and touchpad problem in windowsxp - comp ...... comp.lang.asm.x86 Dell 8500 RAM usable in desktop? - comp.laptops Acer Apire 3000 keyboard and touchpad problem in ... LSA Disk Sector Read - using int 13h ah 42 (extended ... Disks with 256-byte sectors - comp.periphs.scsiLSA Disk Sector Read - using int 13h ah 42 (extended read) - comp ... struct disk_packet //needed for int13 42h { BYTE size_pack; //size of packet must be 16 or 16 ... Reading Serial data through Simulink Input Packet - comp.soft-sys ...LSA Disk Sector Read - using int 13h ah 42 (extended read) - comp ... Reading packets into a buffer - comp.os.linux.networking ... Reading Serial data through Simulink ... how to read bios version using C/C++ - comp.unix.programmer ...Reading Emulex FC HBA Card Firmware - comp.unix.solaris Does ... LSA Disk Sector Read - using int 13h ah 42 (extended read) - comp ... Third, you first need to check if the ... Change sector size - comp.periphs.scsiLSA Disk Sector Read - using int 13h ah 42 (extended read) - comp ... Change sector size - comp.periphs.scsi LSA Disk Sector Read - using int 13h ah 42 (extended read ... short read 0x2000 chars read error - comp.unix.solarisLSA Disk Sector Read - using int 13h ah 42 (extended read) - comp ..... out "0" so that is no error ... major "Deja Vu," after reading ... to have an extended read ... Dell 8500 RAM usable in desktop? - comp.laptopsLSA Disk Sector Read - using int 13h ah 42 (extended read) - comp ... Dell 8500 RAM usable in desktop? - comp.laptops LSA Disk Sector Read - using int 13h ah 42 (extended ... Reading packets into a buffer - comp.os.linux.networking ...LSA Disk Sector Read - using int 13h ah 42 (extended read) - comp ..... m experiencing major "Deja Vu," after reading the ... LSA Disk Sector Read - using int 13h ah 42 ... problem with int 13h function - comp.lang.asm.x86Reading packets into a buffer - comp.os.linux.networking ... problem with int 13h function - comp ... LSA Disk Sector Read - using int 13h ah 42 (extended ... clcm.htm ... surface offset not working in section view - comp.cad.solidworks ...LSA Disk Sector Read - using int 13h ah 42 (extended read) - comp ... surface offset not working in section view - comp.cad.solidworks ... LSA Disk Sector Read - using int ... Variable Length Packets - comp.unix.programmer... assert N <= MAX; --- paranoia ... is to use textio for reading ... LSA Disk Sector Read - using int 13h ah 42 (extended read) - comp ..... pragma pack(1) typedef struct disk ... LSA Disk Sector Read - using int 13h ah 42 (extended read) - Page 2LSA Disk Sector Read - using int 13h ah 42 (extended read) - ASM x86 ASM 370 . This is a discussion on LSA Disk Sector Read - using int 13h ah 42 (extended read ... LSA Disk Sector Read - using int 13h ah 42 (extended read)LSA Disk Sector Read - using int 13h ah 42 (extended read) - ASM x86 ASM 370 . This is a discussion on LSA Disk Sector Read - using int 13h ah 42 (extended read ... 7/22/2012 1:21:24 PM
|