Microsoft eMbedded Visual C++ 4.0

Well I was looking for a way to cross compile to the MIPS and also if I could use my old Platform builder 2.11… Anyways Platform builder has cross compilers, but no libraries, I figured you need the eMbeded Visual C++.. And as luck has it, you can download it right here!. Also you’ll probably want service pack 4.(local mirror), and don’t forget the code TRT7H-KD36T-FRH8D-6QH8P-VFJHQ

System Requirements

  • Supported Operating Systems: Windows 2000; Windows XP
  • Microsoft Windows® 2000 Professional SP2, Microsoft Windows 2000 Server SP2, or Microsoft Windows XP Professional
  • A desktop computer with a Pentium-II class processor, 450 MHz or faster
  • 96 MB (128 MB recommended) memory for Windows 2000 Professional or Windows XP Professional. 192 MB (256 MB recommended) memory for Windows 2000 Server.
  • 200 MB hard disk space
  • CD-ROM drive
  • VGA or higher-resolution monitor. A Super VGA (800 x 600 or larger) monitor is recommended.
  • Mouse or compatible pointing device

If your machine is NOT up to this kind of capability, then you can download the older eMbedded Visaul C++ 3.0, that will run on Windows NT 4.0 (i386 of course). Purdue also had a nice walkthrough on installing the 3.0 tool kit.

I DO recommend that you install IIS on your cross compiling machine, as it’s an easy way to move your object files to the MIPS host for linking.

It is worth noting that Visual C++ 4.0’s emulator will NOT run under Virtual PC.. They use the same call set, and it thinks VPC is Windows CE… I know it’s confusing.

I would imagine everyone could run this. Well if they were so inclined.. Well the installation is pretty simple but now for the ‘fun’ stuff.

First let’s download the source code to Quake.. ID software has been most kind to provide the Quake engine under the GPL!. So we can use it for a MIPS cross compile test.. (As far as I know there is no Dec Alpha cross compiler, but there is a PowerPC.. Anyone use a PowerPC NT machine?). You can download it here. .This went nowhere, as it turns out WindowsCE and Windows NT use different models for floating point, and are incompatible.

Ok with your embedded tools installed, we are now going to merge our Visual C++ MIPS CD so we use it for libraries & include files.. Since we are all going to use the same compiler it’ll be somewhat easy.. I’m using the tools out of “C:\Program Files\Microsoft eMbedded C++ 4.0\EVC\WCE400”

11/27/2001. 03:00 AM........ 1,073,152 C1XX_MP.DLL
11/27/2001. 03:00 AM.......... 581,632 C1_MP.DLL
11/27/2001. 03:00 AM........ 1,056,768 C2_MP.DLL
11/27/2001. 03:00 AM........... 69,632 CLMIPS.EXE
06/13/2001. 03:00 AM.......... 180,276 MSPDB60.DLL

To make it “feel” like visual c++ 2.0 I’m going to put them in the c:\msvc20\bin directory on my HOST pc (Vista Pro x64).. Then I simply copy the include & lib directory from the MIPS Visual C++ CD into the corresponding directories on my host.. We are ALMOST there.

The next thing I did was to grab an intel copy of Visual C++ 2.0 (I almost be dammed near all of them can do this..) and take it’s linker.. The linker out of the embedded tools is obsessed with the WindowsCE subsystem which won’t help us at ALL.

09/16/1994. 01:00 PM........... 67,584 DBI.DLL
09/16/1994. 01:00 PM........... 12,980 LINK.ERR
09/16/1994. 01:00 PM.......... 420,352 LINK.EXE

Go ahead and place those files into the c:\msvc20\bin directory.

Now we just need to create a simple batch file to keep our environment in order:

set LIB=c:\msvc20\lib
set PATH=c:\msvc20\bin;%path%
set include=c:\msvc20\include

Save that to something like mipvars.cmd, and run it & we should be ready to start compiling!

To test the cross compiler I’m going to build a SIMPLE program that has 2 files.

hi.c


#include <stdio.h>

extern int bob(void);

void main(void)
{
printf("%d",bob());
}

bob.c

int bob(void)
{
return 3;
}

Ok, now we compile it like so:

C:\msvc20>clmips *.c -o bob.exe
Microsoft (R) C/C++ Optimizing Compiler Version 12.20.9419 for MIPS R-Series
Copyright (C) Microsoft Corp 1984-2001. All rights reserved.

bob.c
hi.c
Generating Code...
Microsoft (R) 32-Bit Incremental Linker Version 2.50
Copyright (C) Microsoft Corp 1992-94. All rights reserved.

/out:bob.exe
/out:bob.exe
bob.obj
hi.obj
LINK : error LNK1104: cannot open file "corelibc.lib"

Oh no trouble!. Because this was all ripped from the embeded tools it wants to think it has corelibc not libc.. But we can cheat, just copy libc.lib to corelibc.lib and I’ve also copied rpcndr.lib to coredll.lib to satisfy the linker.. Now when we re-compile:

C:\msvc20>clmips *.c -o bob.exe
Microsoft (R) C/C++ Optimizing Compiler Version 12.20.9419 for MIPS R-Series
Copyright (C) Microsoft Corp 1984-2001. All rights reserved.

bob.c
hi.c
Generating Code...
Microsoft (R) 32-Bit Incremental Linker Version 2.50
Copyright (C) Microsoft Corp 1992-94. All rights reserved.

/out:bob.exe
/out:bob.exe
bob.obj
hi.obj

That’s right, we got an executable!. Now if you run it on your x86(or x64) host you’ll get this:

c:\msvc20\bob.exe is not a valid Win32 application.

And of course, since you installed IIS on your HOST (or cross compiling VM) you can connect to it from your MIPS VM, download the exe & run it.

MIPS cross compile
MIPS cross compile

I’m kind of surprised it worked.. It does go to show though, that somewhere inside Microsoft they have some COOL cross compiler technology, it’s just too bad they didn’t make it into an easy package for the RISC stuff.. But now that the MIPS is coming back to life via Qemu, and NT 4.0 can be had for $5 a retail box on ebay, I figure it’s worth this much for those people who can find Visual C++ for MIPS/RISC.

13 thoughts on “Microsoft eMbedded Visual C++ 4.0

  1. There is one important caveat here, if your program uses floating point it currently does not compile correctly, and the linker freaks out…

    Ive transfered the object files to the mips host, and its linker breaks as well.

    However building it on the MIPS host, and transfering the objects to the pc, and it links correctly..

    There is something weird with the CE'ized Visual C++ for the MIPS when it comes to floating point math.

  2. Raymond Chen reminded me about these compilers this morning, so I figured I’d try something like this and then found you’d already done it. Some notes for the next guy:

    * On my Win8 64 bit machine, eVC4’s setup fails to install the virtualization part. That’s not fatal for the install, but it is fatal for installing SP4 later. Everything that follows is using the original eVC4 bits.
    * I used link from Visual C++ 4 rather than 2. Visual C++ 5 is the first one that complains if you tell it to use /MACHINE:MIPS and fail to tell it to use the WINDOWSCE subsystem.
    * Because the compiler is newer than the linker, it can emit a range of things that the linker cannot consume. When this happens, the linker explodes with incredibly unhelpful error messages. In particular, /GF and /Gy don’t work, and I can’t get it to emit .PDB files, but using /DEBUGTYPE:COFF can include debug information in the executable. This is frustrating because the native Visual C++ 4 compiler does support /GF and /Gy, and not having these results in significantly larger executables.
    * In addition to taking the linker from something that can target real NT MIPS, you also need to take RC and its friends, including cvtres. It looks like RC will emit a .RES file and cvtres is invoked implicitly by the linker to convert the .RES into a true object, so these things are a bit of a bundle. Without this, when running the linker you’ll help from cvtres indicating it was invoked with the wrong parameters.
    * Somewhat unrelated to eVC specifically, but because NT MIPS support ended so early there aren’t really facilities that software can use beyond what (real) Visual C++ 4 provides, so using eVC is useful for cross compilation and performance but doesn’t add much functionality. It might improve some C++ support, but then, without an NT CRT that might not be useful anyway.

    I haven’t tried yet, but it might also be worth trying eVC3, which is Visual C++ 5 based, which should more closely match the linker and have fewer restrictions. And, it might be possible to just hack out the stupid linker subsystem complaint, and use the linker that eVC4/Visual C++ 6 would expect; I wonder if the code for generating NT MIPS executables is still buried in there somewhere.

  3. Last night I made a prediction that the eVC linker might still have NT MIPS code in there, and that prediction was right. After making this change I have /GF and /Gy again, and my binaries are half their previous size. I think only the first two bytes of the change are really needed, the rest are nops to realign to the next legitimate instruction for cleanliness.

    C:\>link /?
    Microsoft (R) Incremental Linker Version 6.24.1243
    Copyright (C) Microsoft Corporation. All rights reserved.

    C:\>sha256sum `which link.old`
    b2f5263e7022823e4f5742772552e4a973d4d73170457965474c069b8db75dce link.old

    C:\>fc /b `which link.old` `which link`
    Comparing files P:\DEV\BIN\MIPS\LINKHACK\link.old and P:\DEV\BIN\MIPS\LINKHACK\LINK.EXE
    0005CD66: 66 EB
    0005CD67: 83 1A
    0005CD68: B9 90
    0005CD6A: 00 90
    0005CD6B: 00 90
    0005CD6C: 00 90
    0005CD6D: 09 90
    0005CD6E: 74 90
    0005CD6F: 12 90

    • Wow that’s pretty great! Although now I not only need to try it, but I wonder if any of this works with floating point code at all.

      And of course the lack of native hardware is always a drag, MIPS machines seem to be the rarest to find.

      • From poking around it looks like the “real” Visual C++ 4 compiler just assumes the presence of floating point hardware, whereas the eVC compiler is capable of emulating floating point and defaults to emulation, which adds library calls to coredll.dll or something that won’t exist on NT MIPS. The eVC compiler uses /QMFPE to enable floating point emulation and /QMFPE- to use floating point hardware. After telling it to use floating point hardware, I can generate a simple floating-point hello world that seems to work fine. I don’t know if that’s the same thing you were seeing, but floating point on NT MIPS does work with this compiler, at least in the basic case.

          • Now try to run the x86 embedded VC MIPS cross compiler on that MIPS machine using wx86 😉
            Why are you showing me those MIPS NT stuff again – it distracts me – because i want it on a real processor very bad :<

          • I’m torn. If I had the means I’d probably want a modern AT, with some current gen processor, and ISA bus.

            But a MIPS box even with ISA would be awesome too.

            How hard is it to write a HAL?

          • BTW. Linux KVM also supports virtualization on MIPS, both hardware assisted and software by fault managing. SW one needs you to relocate your virtualized kernel, guess that’s not doable with NT as guest.

    • One more:

      P:\dev\bin\mips\linkhack>cvtres /?
      Microsoft (R) Windows Resource To Object Converter Version 5.00.1720.1
      Copyright (C) Microsoft Corp. 1992-1997. All rights reserved.

      P:\dev\bin\mips\linkhack>sha256sum CVTRES.EXE
      5e8377423582f57a94432209405fc3a96615e1799cbfab62787bed6ff40f8fe5 CVTRES.EXE

      P:\dev\bin\mips\linkhack>fc /b cvtres.exe cvtres2.exe
      Comparing files CVTRES.EXE and CVTRES2.EXE
      00000EAE: 74 EB

      • Not sure why it took so long, but I finally made the modifications after going through a few releases to find that exact same linker. It worked. cross built hyperoids in a second. It’s everything a cross compiler should have been!

        • On to PowerPC! (Seriously, Tenox has been asking – is this why you’re looking too?)

          I took a Visual C++ 5 cross compiler, which is confusingly bundled in the “Windows CE toolkit for Visual C++ 6” under the WCE200 directory, and tried it with a Visual C++ 4.2 linker. So far no luck – it complains about unresolved externals with “__savegpr__nn” and other assembly routines from msvcrt.lib. Since msvcrt.lib came from the RISC Visual C++ 4.0 and I’m using a 4.2 linker, I doubt the linker is really the problem though. Just for kicks I tried the same exercise as here, and using the Visual C++ 5.0 CE linker reports “invalid fixup found, type 0x0808” in kernel32.lib.

          I think fixing it implies getting new Visual C++ 5.0 compatible assembler stubs, or shims to the existing ones. These routines are provided as objects only (not real asm source) in the RISC Visual C++ 4.0. So although I haven’t succeeded yet, it feels tantalizingly close.

Leave a Reply