Errors: cannot use 16-bit register with a 32-bit address 
Author Message
 Errors: cannot use 16-bit register with a 32-bit address

Hallo,

I just try to assemble (with masm 6.11) some old 16bit asm moduls
to 32 bit (win32/NT) and get a lot of errors.

My asm knowleadge is very weak and I don't know
if it is necessary to change the registers from e.g. ax to eax ...
or even it is possible to do this.

Enclosed some compile option, header files and source,
I would need some help to do assemble this in the right way.

ml /c /coff /Cx /W3 /Zm %1.asm > %1.err

PAGE 66,130

.586
.MODEL  flat, stdcall

LARGPROG EQU 1
LARGDATA EQU 1

.XLIST
;
;
; This file contains macros for Microsoft C (version 3.0 or later)
;
;
;
; macros to load register(s) with a given (by number) argument
;
ARGLODV  MACRO REG,NUM
  mov REG,[bp+_ARGOFF&NUM]
  ENDM

ARGLODP  MACRO SREG,OREG,NUM
 IF LARGDATA EQ 0
  mov OREG,[bp+_ARGOFF&NUM]
 ELSE
  l&SREG OREG,[bp+_ARGOFF&NUM] ;generates an LDS or LES
 ENDIF
  ENDM

ARGLODF  MACRO SREG,OREG,NUM
 IF LARGPROG EQ 0
  mov SREG,cs
 ELSE
  mov SREG,[bp+_ARGOFF&NUM+2]
 ENDIF
  mov OREG,[bp+_ARGOFF&NUM]
  ENDM

;
; macros to begin and end the code segment
;
CODEINI  MACRO EXTRNLST
 IF LARGPROG EQ 0
_TEXT  SEGMENT BYTE PUBLIC 'CODE'
  ASSUME CS:_TEXT
   IFNB <EXTRNLST>
     IRP EXTRNMOD,<EXTRNLST>
  EXTRN _&&EXTRNMOD:NEAR
     ENDM
   ENDIF
 ELSE
   IFNB <EXTRNLST>
     IRP EXTRNMOD,<EXTRNLST>
  EXTRN _&&EXTRNMOD:FAR
     ENDM
   ENDIF
PF_TEXT  SEGMENT BYTE 'CODE'
  ASSUME CS:PF_TEXT
 ENDIF
  ENDM

CODEEND  MACRO
 IF LARGPROG EQ 0
_TEXT  ENDS
 ELSE
PF_TEXT  ENDS
 ENDIF
  ENDM
;
; macros to begin and end the static data segment
;
DATAINI  MACRO
DGROUP  GROUP _DATA
_DATA  SEGMENT WORD PUBLIC 'DATA'
  ASSUME DS:DGROUP
;  ASSUME DS:_DATA
  ENDM

DATAEND  MACRO
_DATA  ENDS
  ENDM

;
; macros to begin and end procedures
;
  VALARG EQU 0
  PTRARG EQU 1
ARGSET  MACRO NUM,TYP       ;little macro used by PROCINI to set constants
  _ARGOFF&NUM = _ARGOFFN
  _ARGCNT     = _ARGCNT + 1
  _ARGOFFN    = _ARGOFFN + 2
 IF LARGDATA NE 0  AND  TYP EQ PTRARG
  _ARGOFFN    = _ARGOFFN + 2
 ENDIF
  ENDM

PROCINI  MACRO PNAME,ARGTYPES
  PUBLIC _&PNAME
 IF LARGPROG EQ 0
_&PNAME  PROC NEAR
  _ARGOFFN = 8
 ELSE
_&PNAME  PROC FAR
  _ARGOFFN = 10
 ENDIF
 IF LARGDATA EQ 0
  mov ax,ds
  mov es,ax
 ELSE
  push ds
  _ARGOFFN = _ARGOFFN + 2
 ENDIF
  push bp
  push si
  push di
  mov bp,sp
 IFNB <ARGTYPES>
  _ARGCNT = 0
     IRP ARGTYP,<ARGTYPES>
  ARGSET %_ARGCNT,ARGTYP
     ENDM
 ENDIF
  ENDM

PROCEND  MACRO PNAME
  pop di
  pop si
  pop bp
 IF LARGDATA NE 0
  pop ds
 ENDIF
  ret
_&PNAME  ENDP
  ENDM

;
; macros to load function return values
;
RETLODV  MACRO EXPR
 IFDIF  <ax>,<&EXPR>
  mov ax,EXPR
 ENDIF
  ENDM

RETLODP  MACRO SEGEXPR,OFFEXPR
 IFDIF <ax>,<&OFFEXPR>
  mov ax,OFFEXPR
 ENDIF
 IF LARGDATA NE 0
   IFDIF <dx>,<&SEGEXPR>
  mov dx,SEGEXPR
   ENDIF
 ENDIF
  ENDM

;
; marcro to make and external call
;

XTRNCALL MACRO EXTERNMOD
  call _&EXTERNMOD
  ENDM

;
; macro to return the Program Segment Prefix's segment address
;
PSPSEG  MACRO
  DATAINI
  EXTRN __psp:WORD
  DATAEND
  mov ax,__psp
  ENDM

MEMINUSE MACRO
  DATAINI
  EXTRN __abrktbe:WORD
  EXTRN __psp:WORD
  DATAEND
  mov bx,__abrktbe
  mov ax,[bx]
  mov bx,[bx+2]
  add ax,0FH
  rcr ax,1
  mov cl,3
  shr ax,cl
  add ax,bx
  sub ax,__psp
  ENDM
.LIST

  CODEINI

  PROCINI _wndinit,<VALARG,VALARG>
  ARGLODV dx,0
  ARGLODV ax,1
  mov word ptr cs:oldiv,ax
  mov word ptr cs:oldiv+2,dx
  PROCEND _wndinit

  PROCINI wndbios,<VALARG>
  ARGLODV ax,0
  xchg ax,cs:biosflag
  RETLODV ax
  PROCEND wndbios

  PROCINI _wndgloc,<PTRARG,PTRARG>
  xor bh,bh
  mov ah,3
  pushf
  call cs:oldiv
  xor ah,ah
  mov al,dh
  ARGLODP es,bx,0
  mov es:[bx],ax
  ARGLODP es,bx,1
  mov al,dl
  mov es:[bx],ax
  PROCEND _wndgloc
;
;
  CODEEND
  end

Thanks
Andreas



Sun, 01 Feb 2004 05:27:39 GMT  
 Errors: cannot use 16-bit register with a 32-bit address
On Tue, 14 Aug 2001 23:27:39 +0200, "Andreas Reisenhofer"

Quote:

>Hallo,

>I just try to assemble (with masm 6.11) some old 16bit asm moduls

I don't think that will work very well, if at all.
Quote:
>to 32 bit (win32/NT) and get a lot of errors.

<snip>
--
Arargh (at enteract dot com)    http://www.arargh.com


Sun, 01 Feb 2004 06:15:47 GMT  
 Errors: cannot use 16-bit register with a 32-bit address
Hi,

Could you give any tips would I could do?
Write the code complete new in win32 asm?

reg.
Andreas

Quote:
> >Hallo,

> >I just try to assemble (with masm 6.11) some old 16bit asm moduls
> I don't think that will work very well, if at all.
> >to 32 bit (win32/NT) and get a lot of errors.
> <snip>
> --
> Arargh (at enteract dot com)    http://www.arargh.com



Mon, 02 Feb 2004 04:15:36 GMT  
 Errors: cannot use 16-bit register with a 32-bit address
Quote:
> Write the code complete new in win32 asm?

Yes and no. As far I can see, the macros are very specific to 16-bit memory
models.
Useless for the memory model used in Win32.
Forget the macros and rewrite the code depending on them.
Better: move to a higher level language which will deal with Win32 specific
stuff, and
only use assembler for the parts where assembler will make a big difference.

H



Mon, 02 Feb 2004 15:07:34 GMT  
 Errors: cannot use 16-bit register with a 32-bit address

Quote:

> Hi,

> Could you give any tips would I could do?
> Write the code complete new in win32 asm?

Basically, re-writing will probably be your best bet for a fuller
flavour...because Win32 is not just going from 16-bits to 32-bits, it works
in a _totally different_ way to DOS because of the whole
windowing/protection thing...the main problems you're going to have is that:

    1. Segment registers aren't used at all in Win32...it uses the "flat"
model, where all the segments are set to the same 4Gb big segment...that is,
_all_ your addresses will now be 32-bits near and there won't normally be
any far addressing at all...except for fs, which has some per-thread stuff
you can read (but most programs don't make use of this thing :), you will
not ever need to touch a single segment register in your whole code (there's
not even really the need to generally use segment overrides either because
they are all set to the same 4Gb address space...the only difference between
the segment registers is the access rights they have (i.e. CS will be
read/execute only :), not the addresses they cover :)...knowing something
about how the CPU works in protected mode is a help here, maybe, so you can
understand how segment registers don't work as they do in real mode and how
this flat model thing works...but, to be honest, this is a really a far, far
simpler thing because it, basically, removes the segment registers out of
the equation totally...you can now just think of memory as one big 4Gb chunk
(obviously, this is going to be virtualised by the OS, as most machines
don't carry 4Gb RAM...but, again, the OS takes these considerations out of
the equation, so you don't need to worry about how this works under the
hood...although, if you have specific requirements, you can control memory a
bit using the "VirtualAlloc"/"VirtualFree"/"VirtualProtect" APIs...that'll
let you do groovy stuff like reserve (but not allocate :) a chunk of memory
and then "commit" them (actually allocate them in physical RAM :) as and
when necessary :)...

    2. Direct hardware access is out too...as you probably know form day to
day Windows use, Windows uses device drivers...these do all the direct
hardware access in the system (even Windows itself uses them :) and they
provide a standardised interface to the hardware...so that all hardware
looks the same from Windows' point of view...instead, you call API which
will call the device drivers in turn and, in a sense, you program for
"virtual hardware" with the standard Windows interface, which makes them all
look the same, regardless of whatever weird piece of hardware is hiding
underneath the device driver...again, this simplifies things
programming-wise because you don't need to write all different bits of code
for all the different possible bits of hardware that exists...rather, you
program Windows itself and then Windows will defer these things to the
device drivers...it's basically abstraction by indirection, much like using
pointers to objects in OO stuff (if you know about this...if not, ignore the
comparison, it's not important, just a way to explain it :)...note, on this
score, that if your DOS program draws its own graphics or something (say, a
DOS game or whatever :), then realise that GDI - the standard video stuff in
Windows - has an emphasis on high-level windowing stuff (you set-up pens and
brushes and things like that...and then call API to draw boxes, circles,
pieces of pie, etc. :) and is not really suited for situations where you
draw your own graphics, such as in a game or CAD or paint package...in those
sorts of cases, you'll have to use the DirectX extensions...which are a
separate thing again and use COM, which is an object-orientated binary
standard...again, this sounds more difficult than it actually is - well,
Windows tends to want to "simplify" things generally, if it can - but it's
yet another new thing to learn and get used to, I'm afraid :(...

    3. Windows is graphical primarily and doesn't follow the teletype model
anymore...so, where the usual DOS program would print some text with a "mov
ah,9;int 21h" style of call, this doesn't really hold for Win32 anymore...if
you're doing a so-called GUI process, then you have all the overhead of
setting up a window and looking after it when events happen (see 4 about
being event-driven :) and would need to specify where, what font and what
size to make your text and would actually "draw" these things when Windows
sends you a message that the window needs to be re-drawn (again, see 4 about
being event-driven, if the idea of the OS calling your program seems a bit
weird because it doesn't happen in DOS :)...there is support for so-called
console processes, where it'll knock up one of those DOS boxes and you can
use some API to print things in a DOS-like manner...basically, Windows has
the whole DOS box thing for compatibility with DOS and, with this "console
process" thing, they expose the interface stuff for use by Win32 programs
(so, note, you can have DOS programs running in a DOS box, you can have a
Win32 program making use of the DOS box interface (a console process...it's
actually a 32-bit Windows program but is just making use of the DOS box
graphical interface stuff :) and a fully-fledged Win32 program with all
those windows and dialogue boxes and everything...it's an often confused
thing between DOS programs and Win32 console programs because they
superficially look the same but, internally, a console process is a Win32
program and follows all the other rules I'm mentioning here...the DOS
program, though, is a plain 16-bit DOS program being run in an emulator...as
I say, people sometimes get initially confused by this because they look
identical on the screen but are actually totally different internally
:)...note: if you've got a typical command-line teletype program here, then
you might want to just move it to being a Win32 console process rather than
a fully-fledged Windows program (or, at least, move it to a console process
first before trying a fully-fledged Windows program :)...it'll _still_ need
a re-write because Win32 is internally different but it won't need a
possible re-design of how it operates...because GUI things behave
differently to the usual DOS teletype stuff (you know, in Windows, you'll
have to implement buttons and listboxes and all that stuff...which your
typical teletype DOS program doesn't fit operationally at all :)...

    4. Windows is event-driven; This is something that sometimes confuses
people moving from DOS to Windows (but it's not hard at all...just it's a
different way of doing things, so you might need to get used to how it
works...and, for a while, you might not be able to easily see how to fit
what you want into the event-driven model :)...basically, when a Windows
starts, it sets up its windows and everything before going into a "message
loop"...now, as part of setting up the windows, you'll specify a "window
procedure" which will accept messages from Windows about various things
happening (such as the user clicking on a menu, closing the window, resizing
it...all that sort of stuff :) and then it will react accordingly to the
message...so, the idea is that you set up your windows on the screen and
enter this message loop thing...then, when some sort of action happens,
Windows sends your program a message, which the message loop will pick up
(the loop will call the "GetMessage" (or, maybe, "PeekMessage") API in a
tight loop and this will pick up messages for the program off the process's
message queue :) and then it will call "DispatchMessage", which'll pass it
onto the window procedure you registered when you create the windows...this
procedure will be called by Windows with the message as its parameters and
then, you'd check to see which message it is and branch off to code that
deals with that situation...as you can see, this model is quite a bit
different from the usual DOS method of doing things from the top of the code
to the bottom (although, of course, you could structure your DOS code this
way too...but, generally, most little DOS programs that teletype things to
the screen don't follow this pattern :)...for instance, after creating my
windows, if I want to print out a message to a window, then this sort of
thing will often be separated out...that is, I would actually want to do all
my output to the window when I get the WM_PAINT message (all the Windows
messages have these symbolic names that start with "WM_", which stands for
"Windows message"...you'd normally have an include file that contains all
these symbolic constants because they are almost always referred to by name
and not value in documentation and when people discuss Windows code :)...so,
I might decide to actually "print" to an internal buffer and not straight to
the window...and, then, reading from that buffer to draw the window when a
WM_PAINT turns up...also, there's the weird idea of sending yourself a
message...for instance, to avoid repeating code in different places, I might
put all the clean-up code for the program in the WM_CLOSE message (which is
sent when the user closes the window in one of the many ways Windows
provides for this :) and, then, if the user chooses "File -> Exit" from the
menu, I'd send myself a WM_CLOSE message to call the clean-up code, rather
than repeat it in more than one place...it's this sort of structuring that's
often alien to someone used to DOS coding and you need to get used to the
way Windows works to spot where these sorts of things could be done :)...oh,
finally, any messages you don't handle yourself, you'd pass onto to Windows'
default window procedure that does the usual default actions...so, in a
sense, you can think of it as Windows sending itself messages BUT that it
passes those messages through your code so you can have your say about what
should happen...you could also, if you're careful, disable standard Windows
actions by not sending this ...

read more »



Tue, 03 Feb 2004 10:30:09 GMT  
 
 [ 5 post ] 

 Relevant Pages 

1. Division 32-Bit/32-Bit with 16-Bit Register

2. 16 and 32 bit Addressing Using BP and EBP Registers

3. 16-bit CAN, 32-bit CANNOT!!!????????????

4. 32-bit bin2ascii with 16-bit registers

5. 32-bit bin2ascii with 16-bit registers

6. 16 bit vs 32 bit addressing

7. Graphics Error 16-bit vs 32-bit

8. 16 Bit C code using 32 bit Ext Mem

9. Using 16 bit fortran libraries with 32 bit fortran

10. 16, 16/32, 32 bit Forths: Pros/Cons?

11. 32 bit ST communicating with 16 bit VB

12. How to use SE at any color resolution (256, 16-bit, 32-bit)

 

 
Powered by phpBB® Forum Software