This statement would be technically legal on its own in x86 real mode if the compiler didn't do null pointer checks. However it would set the divide-by-zero IRQ handler to itself 0000:0000, and when the next division by zero happened, the machine run into UB (likely a reset or halt) because it would jump there, do 4x ADD byte ptr [BX + SI], AL (or ADD byte ptr [EAX], AL) followed by running the remaining interrupt vectors as instructions.
cjensen|2 years ago
sacnoradhq|2 years ago
This is writing sizeof(char) (== 1 almost everywhere) zero to address zero. It is not using a NULL macro or other predefined symbol.
In the real world, this would generally write a byte to address 0000:0000, leading to UB because it would fuck up the divide-by-zero IV.
PS: I used Borland C++ 3.1, Microsoft C++ 3.x and 4.5x, Watcom, and early GNU.
jfbastien|2 years ago
lmm|2 years ago
layer8|2 years ago
But yes, the interrupt table was my first thought when reading the headline.
kevin_thibedeau|2 years ago
saghm|2 years ago
lmm|2 years ago
As for why it's address 0, well, it has to go somewhere, every machine has a CPU so everyone needs an interrupt table even if they don't have much memory. And when memory was precious there was no sense wasting even one byte of it; 0 was a real address on your physical memory chip, so why not use it just like any other?
(The fact that it's "address 0" for "division by 0" is just coincidence as far as I can see; division by 0 just happens to be the first kind of possible CPU interrupt. Perhaps it was the most common one?)
wvenable|2 years ago
layer8|2 years ago
HansHamster|2 years ago
The address can be changed with the LIDT instruction and operating systems nowadays will just put it wherever, but for backward compatibility it is expected to still be at 0000:0000 (not sure how this is handled nowadays in UEFI, but it should still be possible t o set it up that way).
marcosdumay|2 years ago
And yes, some addresses are special. (AFAIK, on all current mainstream architectures.) This is the expected way to set those signal handlers, output (and input) data, configure devices, etc.
That said, there are some gotchas on using specific addresses in C. AFAIK none apply to x86, but it's something you usually do in assembly.