IDA Script: Fixing 16bit pushed data segment references

A good friend has started reversing an old 16bit Borland C++ (3.1?) program, and had lots of stack push data segment offsets that were not correctly cross referencing.

After telling him the shortcuts for manually fixing the issue (press O for the data segment, or Alt-R for any segment offset), he wrote an IDC script to do it en mass.

Thus (made up example code)


push ds;

mov ax, 0x1234;

push ax

should look like:


push ds;

mov ax, ds:dword_1234;

push ax

Here’s his script:

#include <idc.idc>

static main()
{
    auto seg, loc;
    auto movloc, movtarget;
    auto xref;
    auto dsegbase;

    dsegbase = SegByName("dseg") * 16;
    Message("dsegbase=%x\n", dsegbase);

    Message("========================================\n");
    seg = FirstSeg();

    while(seg != BADADDR )
    {
        Message("----------------------------------------\n");

        loc = SegStart(seg);

        if( Byte(loc) != 0xCD || Byte(loc+1) != 0x3F)
        {
            Message("Fixing indirect push [ds:xx] refs from %s\n", SegName(seg));

            while(loc != BADADDR && loc < SegEnd(seg))
            {
                if (GetMnem(loc) != "push" || GetOpnd(loc, 0) != "ds")
                {
                    loc = NextHead(loc, BADADDR);
                    continue;
                }
                loc = NextHead(loc, BADADDR);

                if (GetMnem(loc) != "mov" || GetOpType(loc, 1) != o_imm)
                {
                    loc = NextHead(loc, BADADDR);
                    continue;
                }
                movloc = loc;
                movtarget = GetOpnd(movloc, 0);
                loc = NextHead(loc, BADADDR);

                if (GetMnem(loc) != "push" || GetOpnd(loc, 0) != movtarget)
                {
                    continue;
                }

                // At this point, we know we're pushing a [ds:x] combo.
                //Message("%x: mov %s, %s\n", movloc, movtarget, GetOpnd(movloc, 1));

                // Abort if there already exists a Dxref
                xref = Dfirst(movloc);
                if (xref != BADADDR)
                {
                    continue;
                }

                Message("  Updating %s:%04x\n", SegName(seg), (movloc - seg) & 0xffff);
                OpOff(movloc, 1, dsegbase);
            }
        }

        seg = NextSeg(seg);
    }
}

1 thought on “IDA Script: Fixing 16bit pushed data segment references”

  1. I just ran into exactly the same problem and was well on my way to writing this very script. It saved me a lot of time. Thanks for posting it!

Comments are closed.