c - XMS allocation in 16-bit DOS -


please forgive attempts @ necromancy, need write code 16-bit dos (!). have verify piece of software executes correctly when built 16-bit platform, , discovered our xp workstations can run 16-bit dos apps, makes possible use existing batch test system.

in case, software consists of 1 library , 1 database. smaller databases (up ~150kb) can either defined static global array or read file buffer allocated halloc(), confident library , test tool built correctly.

however, have larger databases test, ~1.8mb. large allocate normally, wrote small support library allocate xms memory. this, can allocate, use (i.e. write , read data) , free 16mb of data in small toy program. however, when using xms facilities in "real" application, following error:

the ntvdm cpu has encountered illegal instruction. cs:0000 ip:00ba op:0f 04 10 0e 51 

googling on error gave little relevant results, type of error seems blamed on miscellaneous malware.

the code base strict c90, compiler used dos builds openwatcom 1.9 using "large" memory model. no warnings or errors while building.

the xms support library follows, error seems occurs after call xmsmalloc():

/* file implements rudimentary xms memory handling.  * documentation on xms api found on http://www.qzx.com/pc-gpe/xms30.txt  */  #include <stddef.h> /* definition of null */ #include <limits.h> /* definition of uint_max */ #include <stdio.h>  /* fprintf , (file *) */  /* allow external configuration of maximum concurrent xms allocations */ #ifndef max_xms_allocations #define max_xms_allocations 4 #endif  /* address of xms driver */ static long xmscontrol;  /* mapping of xms handle <-> normal pointer */ typedef struct {     unsigned int xmshandle;     void huge * xmspointer;  } xmshandlemap;  static xmshandlemap allocmap[max_xms_allocations];  /* set xms driver, returns 0 on success , non-zero on failure */ static int initxms(void) {     char xmsstatus = 0;      if ( xmscontrol == 0 )     {         __asm {         ; xms driver installed?             mov ax,4300h             int 2fh             mov [xmsstatus], al         }          if ( xmsstatus == 0x80 )         {             __asm {             ; address of driver control function                 mov ax,4310h                 int 2fh                 mov word ptr [xmscontrol]  ,bx                 mov word ptr [xmscontrol+2],es             }         }     }      return ( xmscontrol == 0 ); }  /* allocate slab of memory xms */ void huge * xmsmalloc(long unsigned int size) {     unsigned int kb;     unsigned int xmsstatus = 0;     unsigned int xmshandle = 0;     void huge * xmspointer = null;     int n;      /* if can not initialize xms, allocation fails */     if ( initxms() )         return null;      /* not possible allocate more kilobytes 16-bit register can hold :-) */     if ( size / 1024 > uint_max )         return null;      /* next free entry in handle <-> pointer mapping */     ( n = 0; n < max_xms_allocations; n++ )     {         if ( allocmap[n].xmspointer == null )             break;     }      if ( n == max_xms_allocations )         return null;      kb = size / 1024 + (size % 1024 > 0);      __asm {     ; allocate [kb] kilobytes of xms memory         mov ah, 09h         mov dx, [kb]         call [xmscontrol]         mov [xmsstatus], ax         mov [xmshandle], dx     }      /* check if xms allocation failed */     if ( xmsstatus == 0)         return null;      __asm {     ; convert xms handle normal pointer         mov ah, 0ch         mov dx, [xmshandle]         call [xmscontrol]         mov [xmsstatus], ax          mov word ptr [xmspointer],  bx          mov word ptr [xmspointer+2],dx     }      if ( xmsstatus == 0 )     {         /* lock failed, deallocate handle */         __asm {         ; free xms handle             mov ah, 0ah             mov dx, [xmshandle]             call [xmscontrol]          ; return value not interesting          ;   mov [xmsstatus], ax         }         return null;     }      /* create entry in handle <-> pointer mapping */     allocmap[n].xmshandle = xmshandle;     allocmap[n].xmspointer = xmspointer;      return xmspointer; }  /* free pointer allocated xmsalloc */ void xmsfree(void huge * xmspointer) {     int n;      if ( xmspointer == null )         return;      if ( initxms() )          return;      ( n = 0; n < max_xms_allocations; n++ )     {         if ( allocmap[n].xmspointer == xmspointer )         {             int xmshandle = allocmap[n].xmshandle;              __asm {             ; unlock handle can free memory block                 mov ah, 0dh                 mov dx, [xmshandle]                 call [xmscontrol]              ; free xms memory                 mov ah, 0ah                 mov dx, [xmshandle]                 call [xmscontrol]              ; return value ignored             }              /* clear handle <-> pointer map entry can reused */             allocmap[n].xmshandle = 0;             allocmap[n].xmspointer = null;              return;         }     } }  /* write memory report debugging purposes */ void xmsreport(file * stream) {     int xmsversionnumber = 0;     int xmslargestblock = 0;     int xmstotal = 0;      if ( initxms() )      {         puts("could not initialize xms driver!");         return;     }      __asm {     ; driver version number         mov ah,00h         call [xmscontrol] ; xms version number         mov [xmsversionnumber], ax      ; amount of free xms memory         mov ah, 08h         call [xmscontrol]         mov [xmslargestblock], ax         mov [xmstotal], dx     }      fprintf(stream, "xms version number: %d\n", xmsversionnumber);     fprintf(stream, "largest available block: %d kb (%d kb total)\n", xmslargestblock, xmstotal); } 

some concrete questions:

  1. where can find more information error message (i guess op means opcode, other fields?)
  2. does xms api reference found still apply when running on windows xp, or there newer version should reference?
  3. could screwed system state inline assembler? how should resolve that?
  4. do have better idea on how solve this? :-) dos extenders seem require 32-bit mode, whole point of exercise using 16-bit mode.

i see 2 problems.

1st: make sure compiler using far call instead of near call otherwise jump wrong segment , execute unknown code , possably generating invalid opcode... seems happening. try "call far [xmscontrol]" in code if compiler defaults near calls.

2nd: ntvdm.exe runs code in virtual 86 mode , not true real mode. while true windows xp supports 16 bit apps, has limited support. may run other problems database down line because of that. example wont able access usb, can't print on usb printer , need use old parallel port style printer. luck findign 1 of used @ garage sale...


Comments

Popular posts from this blog

asp.net - repeatedly call AddImageUrl(url) to assemble pdf document -

java - Android recognize cell phone with keyboard or not? -

iphone - How would you achieve a LED Scrolling effect? -