Errors: cannot use 16-bit register with a 32-bit address
Author |
Message |
Andreas Reisenhofe #1 / 5
|
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 |
|
|
Arargh #2 / 5
|
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 |
|
|
Andreas Reisenhofe #3 / 5
|
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 |
|
|
Herman Dullin #4 / 5
|
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 |
|
|
Beth #5 / 5
|
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 |
|
|
|