Author Topic: Unexpected division by zero error  (Read 19913 times)

Offline madanra

  • Jr. Member
  • *
  • Posts: 3
Unexpected division by zero error
« on: September 04, 2010, 11:15:31 AM »
I'm getting an unexpected division by zero error when using %define and equ. The smallest example I've been able to make is this:
This code works:
Code: [Select]
%define sector(b) ((b-$$)>>9)
dd 32/sector(dataend)
times 4088 db 0
dataend:
but this doesn't:
Code: [Select]
%define sector(b) ((b-$$)>>9)
spt equ sector(dataend)
dd 32/spt
times 4088 db 0
dataend:
giving the error
Code: [Select]
test.asm:3: error: division by zeroI've confirmed that spt has the expected value (8) by
Code: [Select]
%define sector(b) ((b-$$)>>9)
spt equ sector(dataend)
dd spt
times 4088 db 0
dataend:
and replacing spt equ sector(dataend) with spt equ 8 in
Code: [Select]
%define sector(b) ((b-$$)>>9)
spt equ 8
dd 32/spt
times 4088 db 0
dataend:
works fine.
Using %define instead of equ:
Code: [Select]
%define sector(b) ((b-$$)>>9)
%define spt sector(dataend)
dd 32/spt
times 4088 db 0
dataend:
also works fine, so presumably I'm misunderstanding equ. What's wrong?

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: Unexpected division by zero error
« Reply #1 on: September 04, 2010, 04:26:12 PM »
Interesting observation, Madanra! I think it's a bug report...

I have developed a theory of what's happening. Going back to 2.02, I get "error: symbol 'dataend' not defined before use". The argument to "equ" (and a few other cases) is, or was, a "critical expression". The value needs to be known on the "first pass", or actually on the "next to last" pass. Nasm won't handle a "forward reference" in this position. Adding the "-O" switch enables multiple passes, so eliminates this error (but still gets the "divide by zero").

As of 2.03, unless I'm mistaken, we take an extra pass to resolve forward references, even if multiple passes aren't enabled for optimization purposes. A Good Thing, generally, I think.

Apparently, "spt" is being "provisionally evaluated" as zero on the first pass, in this case. Not a problem, we evaluate it correctly on subsequent passes... unless we divide by it! I'm thinking the "fix" for this may be to tag "spt" as a forward reference, so we don't attempt to divide by it (instead of - or along with - evaluating it as zero?). This is apparently what happens when you do "dd 32/sector(dataend)" - (doing "spt" as a "%define" rather than an "equ" is just a "cut-and-paste", so is equivalent to this).

We'll see if we can get the real developers to take a look at this. In the meantime "don't divide by the result of an 'equ' if it's a forward reference". That's my theory.

Incidentally, "( (b) - $$) >> 9" truncates. You might want to do "( (b) - $$ + 511) >> 9" to "round up". If your "payload" is padded to an even number of sectors, it isn't a problem. Just a thought...

Thanks for the feedback! Apparently no one noticed this problem before!

Best,
Frank


Offline Cyrill Gorcunov

  • NASM Developer
  • Full Member
  • *****
  • Posts: 179
  • Country: 00
Re: Unexpected division by zero error
« Reply #2 on: September 04, 2010, 08:11:19 PM »
Frank, mind to issue bug-report so we would track it then. Thanks.

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: Unexpected division by zero error
« Reply #3 on: September 06, 2010, 09:49:37 PM »
Okay, filed as BR3060662. Thanks again for the great feedback, Madanra!

Best,
Frank


Offline Cyrill Gorcunov

  • NASM Developer
  • Full Member
  • *****
  • Posts: 179
  • Country: 00
Re: Unexpected division by zero error
« Reply #4 on: September 07, 2010, 06:22:39 PM »
thanks, i'll take a look as only get time