delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/1998/08/31/05:00:16

Date: Mon, 31 Aug 1998 12:00:08 +0300 (IDT)
From: Eli Zaretskii <eliz AT is DOT elta DOT co DOT il>
To: Endlisnis <s257m AT unb DOT ca>
cc: djgpp AT delorie DOT com
Subject: Re: Am I retarded -or- Why is my exe size so big?!?
In-Reply-To: <35E980D9.2EB7A55D@unb.ca>
Message-ID: <Pine.SUN.3.91.980831115955.22974E-100000@is>
MIME-Version: 1.0

On Sun, 30 Aug 1998, Endlisnis wrote:

> > compute the linear address with seg*16 + offset.
>
> 	But, if I do that, then I will get an overflow when
> multiplying 'seg' by 16. And I will loose the top 4-bits of the
> address.

You need to promote it, of course: ((int)seg * 16) + offset.  The
linear address is 32-bit anyway, so it doesn't matter when to convert
it to an int.

> typedef unsigned int lword;
> 
> lword a;
> short* b;
> 
> a = (lword)(short*)a;
> b = (short*)(lword)b;
> 
> AFAIK: These 2 lines should do NOTHING (the values of a,b should not
> change at all).

Of course, they don't.  Casting alone usually doesn't do anything.

But your original code didn't just cast.  It shifted bits and used
addition and bitwise AND operations.  That is something different
indeed.

> 	Given that, I don't understand why that line of code I posted earlier
> wouldn't do what I expected and would encourage anyone to give me any lengthy
> expanation they have.

Your code is wrong for several reasons, which I describe below.  But
the point I wanted to make in my previous message was that your
*approach* is wrong: you use pointers to do arithmetics on integers
(the segment and the offset of a real-mode pointer).  It is true that
pointers in DJGPP are just offsets, so they are 32-bit integers.  But
using them for integer computations is a bad idea which will easily
get you into trouble; and it certainly defeats many useful diagnostics
that the compiler could emit to help you (since you are coerced to use
type-casts to work around the compiler).  If you need to compute
a*16+b, just do it (by declaring two shorts); do NOT try to pack them
into a single pseudo-pointer and then shuffle the bits around.

Now to the problems with your code:

  - This line:

      DOS = (short*)(((lword)DOS>>12)&0xFFFF0)+((lword)DOS&0xFFFF);

    boils down to an expression like this:

      DOS = (short *)a + b;

    However, adding b to a pointer to a short actually adds 2*b to the
    value of the pointer, because a short is 2 bytes wide.  You need
    to change this line to something like this:

      DOS = (short *)(a + b);

    or, returning to your code:

      DOS = (short*)((((lword)DOS>>12)&0xFFFF0)+((lword)DOS&0xFFFF));

  - The second problem is that your cout line is wrong:

      cout << DOS << " should be 0xC1234\n";

    It should say something like this instead:

      cout << hex << (lword)DOS << " should be 0xC1234\n";

After these two changes, the program works for me as expected, under
any level of optimizations.  But I still think it is a very bad idea
to do it this way.

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019