Incorrectly writing offset to DS in specific nested for loops with optimization enabled
asiekierka opened this issue · comments
I did not manage to write a reproduction that works as a DOS .EXE - no matter what I did, the register allocations arranged themselves differently, not triggering the bug - so I'm attaching the whole main.i
file: https://asie.pl/files/gcc-ia16-20230905-193115.i
However, the assembly generation error is thankfully obvious when pointed out: When compiling the above file with ia16-elf-gcc -O2 -mcmodel=medium -c -o main.o gcc-ia16-20230905-193115.i
, the following ASM sequence gets emitted:
163: 31 ff xor %di,%di
165: 89 f8 mov %di,%ax
167: ba 00 00 mov $0x0,%dx
168: R_386_16 SwanOffset
16a: 8e da mov %dx,%ds
16c: e9 de fe jmp 4d <main+0x4d>
Of particular note is the mov %dx,%ds
sequence, which writes a pointer offset into %ds
. %ds
is not fixed later, leading to later-executed register->memory writes, such as:
6f: 88 44 01 mov %al,0x1(%si)
to write to an incorrect memory location.
This issue does not occur when the bitfield access to sprites[].tile/palette
is replaced with a non-bitfield access, but it's possible to trigger an adjacent issue in this scenario.