Home

WINDOWS ASSEMBLY LANGUAGE & SYSTEMS PROGRAMMING

image

Contents

1. x cycle time A 100 4 3 2 1 E Manipulated Variable Output i i DBL Deadbnd A rf gt p eadbn Bm 55 Noise alve Deadband 362 Windows Assembly Language amp Systems Programming Narrow target The next negative point is that LabView is optimised for use by market Front panel amp top icon leon hierarchy engineers and scientists and this is reflected throughout its design It is absolutely superb for data acquisition control mathematic processing and image work It was never really intended to be a commercial high volume product so you dont use it to develop high volume applications You use LabView for custom one off or low quantity jobs However since people have discovered that LabView is good for just about everything and is very easy to use once you get used to the dataflow concept the original market domain has tended to diversify People are now selling stand alone applications to a larger market in particular this has happened since LabView was released on the PC in 1993 Integration with Assembly Since LabView is optimised for engineering and scientific applications its strengths are on the I O side which ties in strongly with the kind of things you normally use assembly for So if you use LabView to control all the machinery in your factory and you also want to do some low level optimisation how can you integrate assembly into the
2. DEBUGBREAK Not documented in the SDK Forces a break to the debugger DEBUGOUTPUT Available with Windows 3 1 only Sends formatted messages to a debugging terminal DEFHOOKPROC Calls the next filter function in a filter function chain CallnextHookEx DIRECTEDYIELD Not documented in SDK 3 0 Forces execution to continue at a specified task BLY EAY WY TY LAOS WV O WUE VIOO 2 DISABLEOEMLAYER Not documented in the SDK Turns off Windows display keyboard and mouse and changes to text mode restores DOS I O Complement is ENABLEOEMLAYER DOS3CALL Issues a DOS INT 2 1 h interrupt but doesnt use INT ENABLEHARDWAREINPUT Enables or disables keyboard and mouse input throughout the application ENABLEOEMLA YER Not documented in the SDK See Chapter 9 Complement of DISABLEOEMLAYER ENABLEWINDOW Enables or disables keyboard and mouse input to a specified window or control FATALEXIT Displays current state of Windows on debugger monitor and prompts on how to proceed FBEESELECTOR Frees a selector originally allocated by ALLOCSELECTOR O ALLOCCSTODSALIAS Q or ALLOCDSTOCSALIAS functions GETASYNCKEYSTATE Returns interrupt level information about the key state GETCURRENTPDB Returns the current DOS Program Segment Prefix PSP GetCommandLine GetEnvironmentStrings GETCUBBENTTIME Returns the time elapsed since the system was booted GETDOSENVIRONMENT Retrieves the environment stri
3. The use of the 16 bit versions LOADLIBRARY and GETPROCADDRESS is described in Chapter 9 The principles apply to the 32 bit versions also WOW ee briefly here they are functions CallProc32W CallProcEx32W called from Used by 16 bit code to call an entry point function in a 32 bit 16 bit code DLL FreeLibrary32W Allows 16 bit code to free a 32 bit thunk DLL that it had previously loaded by using the LoadLibraryEx32W function e GetProcAddress32W Allows 16 bit code to retrieve a value that corresponds to a 32 bit routine e GetVDMPointer32W Allows 16 bit code to translate a 16 bit FAR pointer into a 32 bit FLAT pointer for use by a 32 bit DLL e LoadLibraryEx32W Allows 16 bit code to load a 32 bit DLL iWOW These are a different group of WOW functions functions called from WOW Callbackl 6 WOwWCallback16Ex Used in 32 bit code called from 16 bit code to call back to the J2 bit code aes 16 bit side e WOWGetVDMPointer Converts a 16 16 address to the equivalent FLAT address 222 Windows Assembly Language amp Systems Programming WOWGetVDMPointerFix Converts a 16 16 address to the equivalent FLAT address Unlike the WOWGetVDMPointer function this calls the GlobalFix function before returning e WOWGetVDMPointerUnfix Uses the GlobalUnfix function to unfix the pointer returned by WOWGetVDMPointerFix e WOWGlobalAllocl6 Thunks to the 16 bit version GLOBALALLOC e WOWGlobalAllocLockl6 Combines t
4. more postfix is what pauses the screen TASM32 For 32 bit development you will be using TASM32 EXE TLINK32 TLINK32 EXE and BRC32 EXE The latter is the resource BRC32 32 bit compiler There is also BRCC32 EXE but the documentation tools does not mention anything about it In fact the documentation barely says anything about the resource compilers at all and there 310 Windows Assembly Language amp Systems Programming Fine tuning the installation for stability is no demonstration 32 bit program that utilises them Never mind Uncle Barry figured it all out After installation when I first ran TASM32 it crashed I fiddled around and suddenly it started working Later that night for no apparent reason it crashed again That is it aborted on loading I had no idea why I made some changes and everything has been ok since then I found a reference in the documentation that the WIN INI file should have this entry in WIN INI file Windows spooler yes So I put that in Then I read that the install process puts these two lines into the SYSTEM INI file SYSTEM INI file 386Enh device c tasm bin windpmi 386 device c tasm bin tddebug 386 What is the purpose I asked myself of WINDPMI 386 when Windows already provides DPMI for DOS boxes So I erased that line Example Skeleton Program Ok here it is Thirty two bit coding has certain refinements one of which is the prolog epilog code
5. CCLRBRK Clears the Comm line break state CEVT Returns the address of the Comm event word CEVTGET Clears and gets specified events in the Comm event word CEXTFCN Performs an extended driver function CFLUSH Discards the contents of a receive or transmit buffer COMMWIUTESTIUNG Transmits a block of data over the serial port CSETBBK Initiates a Comm line break state CTX Transmits a single byte before all others in the transmit queue GETDCB Returns the address of the DCB structure for the specified port INICOM Initializes the specified Comm port BEACTIVATEOPENCOMMPORTS Re enables Comm ports disabled by SUSPENDOPENCOMMPORTS READCOMMSTIUNG Reads bytes from the Comm receive buffer BECCOM Reads a byte from the Comm receive buffer BIOS DOS Windows Services 217 e SETCOM Sets the device configuration and state e SETQUE Specifies the memory input output buffers e SNDCOM Places a character in the transmit queue e STACOM Gets the hardware and buffer status of the specified port e SUSPENDOPENCOMMPORTS Temporarily disables all Comm port activity e TRMCOM Closes the specified port Keyboard e DISABLE driver Suspends interrupt callbacks and removes hooks functions e ENABLE Enables calls to the Windows keyboard event procedure e ENABLEKBSYSREQ Enables or disables SysRq key processing e GETBIOSKEYPROC Gets the address of the BIOS interrupt service routine e INQUIRE Returns the ke
6. You could have the habit of putting in front of every label that is to be local to a procedure This seems ok in principle except that I encountered assembly errors that do not make sense to me Apart from my negative personal experience you can take it as good policy to use prefixing as much as possible when using TASM Dont forget to put the LOCALS directive at the start of the file Look ahead to Chapter 6 for examples of using I have had a lot of trouble using in WINASMOO INC Chapter 6 you can see in the listing on page 168 that I defined now as a parameter passed to procedures which according to Borland statement above is global Yet I have reused it in many procedures and in each case it assembles correctly This indicates though I cant find it mentioned anywhere in the manual that the local definition of now overrides any other local definitions So now is not really global It only exists on the stack anyway so sensibly it is only valid for the life of the procedure in which it is declared Borland would you kindly be a little more precise The only difficulty with now would be if you had a statically declared now as well say in the data segment then you have a clash Then it is essential to use or another name Borland has tidied up label scope by using the C like approach found in MASM version 6 in their TASM version 5 0 See Chapter 13 Life of Automatic Dat
7. extensionsnotfnd selectorerror qwerty ret makeringOselector ENDP What you will notice in the above code is that I have not created code or data descriptors What you do see above is the use of selector 28h Ihave obtained the base addresses from ASMRINGO s DS and CS descriptors and to obtain the code FLAT linear address I have added the offset of RINGOFUNC to the base address ofCS and saved the result in flatlin To obtain a FLAT linear address to the data segment I extracted the base address from DS and saved itas flatdatalin Calling VMM Now going up to ring 0 HEAVEN by exactly the same method of and VxD call RINGOCALLGATE will cause entry to RINGOFUNC with services CS 28h the FLAT selector 32 Bit Ring 0 303 HEAVEN Here is some 32 bit ring O code for RINGOFUNC that calls a enhanced VMM function 386P fF INCLUDE vmm tiny inc enables us to call vmm and vxd functions derived from VMM INC in the DDK EXTERN ringOstack DWORD EXTERN defaultOesp DWORD EXTERN defaultOss WORD PUBLIC RINGOFUNC TEXT2 SEGMENT DWORD PUBLIC USE32 CODE ASSUME CS _TEXT2 RINGO FUNC PROG FAR jassuming that no parameters are passed the ring 0 stack contains return EIP return CS old ESP old SS the last two deepest in the stack reference the ring 3 application stack I think DS still points to old data segment so can still use cli make sure actual flag is clear pushfd pushad push ds
8. int active virtual void TEXTOUT int int Program Design 143 Define any other members here void WINDOW TEXTOUT int paraml int param2 actual code for function here This function is the equivalent of textoutmain in the assembly listing class WINCLASSA WINDOW subclass of WINDOW inherits active and TEXTOUT members class WINCLASSB WINDOW override TEXTOUT void TEXTOUT int paraml int param2 void WINCLASSB TEXTOUT int paraml int param2 actual code for function here This function is the equivalent of textoutdlg in the assembly listing create instances WINCLASSA windowl window3 WINCLASSB window2 main code example of early binding window1 TEXTOUT valuel value2 code example of late binding WINDOW ptr ptr amp windowl ptr gt TEXTOUT valuel value2 oe The program starts by declaring a class called WINDOW and the operator data and function members it has I only put in two members active and TEXTOUT After that I put in the actual code for TEXTOUT Notice the syntax for doing this the means that this function belongs to the class named to its left which is WINDOW Subclassing Because I wanted this code to do exactly what the assembly listing with override does page 140 I created two subclasses WINCLASSA and WINCLASSB WINCLASSA is identical in every way to WINDOW but in WINCLASSB I have overridden TE
9. which is official for both 3 0 and 3 1 see page 208 ALLOCCSTODSALIAS is an unofficial alternative With Win95 they all go back to being unofficial There is another interesting related function introduced with TOOLHELP DLL and so is backwards compatible with 3 0 MEMORYWRITED This will copy a block of memory from one segment to another regardless of their attributes Thus it will write to a code segment Actually it is quite easy to get data segment addressability from within an ISR but I ll leave that one for now Data alias Before I show you the actual ISR I ll provide a little bit of extra to code setup code using the abovementioned DPMI service will create alias in LDT of CS mov ax 000Ah push cs pop bx selector to be aliased int 31h returns alias selector in ax push ax POP es mov es dsselector ax save the alias in the code seg Normally I would perform the above aliasing in the install code and save the alias selector in the code segment The ISR can then read it and use it This works as long as the ISR doesn t move in memory The same principle can be used to obtain addressability to the WinApp s data segment Having got into the service routine and established data addressability all that remains is to do something I have used the code from page 246 to produce a tone on the loudspeaker Here it is CODE I ve put this data in the code segment amp selector DW 0 data alias to code se
10. 32 bit instruction pointer EIP CPU Architecture 21 I O services can be provided This is discussed further later in the book Figure 1 9 Basic setup of a GDT OFFSET CONTENT Reserved should be 0 Descriptor for this GDT Descriptor for the IDT Descriptor for DS Descriptor for ES Descriptor for SS Descriptor for CS Descr temp BIOS CS Inside the 286 386 486 etc Mostly I have concentrated on the 386 since the 286 is history You can consider later processors to be functionally equivalent just faster Do not get the idea that later processors such as the Pentium are fundamentally different from the 386 Just about all 32 bit code written today will run on a 386 Most architectural differences are to do with speed enhancements There are some architectural differences between the 386 486 586 686 and Pentium but I have focused here on the basic architecture the 386 This is the common factor underlying them all Everything almost has become 32 bits including 32 bit address and data buses The Instruction Pointer has grown to 32 bits see Figure 1 10 which means that the original rationalization for introducing segment registers has been nullified However the segment registers are still there and still 8 bits the curse of compatibility is still with us 22 Windows Assembly Language amp Systems Programming Memory and 1 0 address spaces Downward compatibility 32 bit registers Thi
11. BX selector for the descriptor to free Returns if function successful UF clear 4x error code 8022h invalid selector Int 31h Function 0002h Segment to Descriptor Maps a Real mode segment paragraph address onto an LDT descriptor that can be used by a Protected mode program to access the same memory Call with AX 0002h BX Real mode segment address Returns if function successful CF clear 390 Windows Assembly Language amp Systems Programming AX selector for Real mode segment if function unsucessful C set AX error code 801 1h descriptor unavailable Int 31h Function 0003h Get Selector Increment Value The DPMI functions Allocate LDT Descriptors Int 3 1h Function 0000h and Allocate DOS Memory Block Int 3 Ih Function 0100h can allocate an array of contiguous descriptors but only return a selector for the first descriptor The value returned by this function can be used to calculate the selectors for subsequent descriptors in the array Call with Ax 0003h Returns CF clear this function always succeeds AX selector increment value Int 31h Function 0006h Get Segment Base Address Returns the 32 bit linear base address from the LDT descriptor for the specified segment Call with AX 0006h BX selector Returns if function successful CF clear CX DX 32 bit linear base address of segment if function unsuccessful set AX error code 3022h inva
12. Both companies have moved toward less printed and more on line documentation My personal viewpoint is that you cant beat a good printed manual which is why the supplementary printed books business is booming TASMS supports 32 bit programming for Windows 95 and NT but the documentation both printed and on line is pitiful The one example program is also pitiful as it is written for TASM 4 So I had to figure it out from scratch I had a 32 bit program written for MASM which I converted Now this is an interesting story and there were nights spent working to 3 00 am trying to figure it out TASMS almost supports all of the features of MASM version 6 1 Therefore the example program given in this chapter though written for TASMS should also be very easy to convert for MASM e TASMS has prototypes for procedures except they are designated by the PROCDESC keyword not PROTO Otherwise the syntax is the same and I was able to create an Include file W32 INC on the Companion Disk in directory TASM32 that is very easy to convert for MASM 32 bit Ring 3 309 e TASMS does not use INVOKE for high level procedures just the plain old CALL keyword e TASMS allows parameters passed to a procedure to be declared on the same line as the PROC declaration but it is not quite so sophisticated as MASM You cannot use MASM s ADDR prefix or the for composing two 16 bit registers into one 32 bit value Howeve
13. Example Skeleton Program ssseee seer errr rene 310 Support Files 0 cece cece e ener eee ener nent eee 314 Postamble sronto aai EAE EEKEREN A 318 14 DOS Win Transitions 319 Preamble cece cee eee eect e renee eee ee eee eanes 319 Interrupt Handlers sees reece eee eee e reece 320 Example Protected Mode ISR Code 321 Problems Issues with the Protected Mode ISRs 323 The Real Mode Handler 00 cece cece ee eens 324 DOS to Win Device Driver TSR 6 e eee eee eens 330 Automatic Loading of Windows Programs Drivers 330 TSR Installation 0 0 0 0 ccc c eee e eee eee ence eee 331 TSR Resident Code cccec cece erence eee e eens 338 Getting it Together esse eee ee eee eer e eens 339 15 Advanced Systems Programming 341 Preamble ccc cece cece reece eee e nace ence eas eneee 341 Mapping Across VMS 0esseee eee erste ete 343 Ch Page Mapping the 4 3G Linear Address Space of a VM to Physical Memory 00 ccc eeeeeeaes 344 The Windows DOS DPMI Relationship 348 Windows Extensions to INT 2Fh 348 The Windows INT 2Fh Relationship 349 Writing Windows Aware DOSApps 349 Sharing Memory Between 16 and 32 bit WinApps 350 Anatomy of a VXD 025 cosak eid aaa viens Gan 351 Maximum Productivity ccc annarra 358 LabView Program
14. GetProcessTimes GetProcessVersion GetProcessWorkingSetSize GetStartupInfo GetThreadPriority GetThreadTimes OpenProcess ResumeThread SetEnvironmentVariable SetPriorityClass SetProcessShutdownParameters SetThreadA ffinityMask 224 Windows Assembly Language amp Systems Programming SetThreadPriority Sleep SleepEx SetProcessWorkingSetSize SuspendThread TerminateProcess TerminateThread TlsAlloc TlsFree TisGetValue TlsSetValue WaitForInputidle WinExec Memory Mapped Files Windows 95 introduces memory mapped tile functions for sharing data between applications CreateFileMapping creates such a tile while MapViewofFile maps it OpenFileMapping and DuplicateHandleQ can be used by processes to access the tile Despite the name file it does not have to be on a disk the file can reside entirely in memory Such a global file is visible to all applications Postamble This chapter is notable more for what it doesnt say than what it does Various functions interrupts and concepts introduced here are developed in the chapters ahead What s in this chapter Direct Hardware Access Preamble This chapter contains practical code to get behind the scenes The first part of the chapter focuses on the issues of direct reading from and writing to memory particularly video RAM and the second part focuses on I O I have shown the use of DPMI INT 3 lh services and of the INT 2Fh extension
15. Notice QUIT also that it is prefixed with si as are all the other menu item parameters of the window You can understand this from the principle of structures The SI register contains the address of the object or the instance of the structure Destroy is a field in this structure Fields can in OOP terminology be data members or function members methods in Pascal terminology The field des t roy does not contain data but a pointer to a routine To effectively use this object oriented approach you need to know the fields of the WINDOW structure and the purpose of each The WINDOW Object TABLE Here is the structure definition of WINDOW It is actually located directive inside WINASMOO INC DATA WINDOW TABLE VIRTUAL definewndclass WORD WINDOWdefinewndclass VIRTUAL create WORD WINDOWcreate VIRTUAL paint WORD WINDOWpaint VIRTUAL command WORD WINDOWcommand VIRTUAL timer WORD WINDOWtimer VIRTUAL resize WORD WINDOWresize VIRTUAL mousemove WORD WINDOWmousemove VIRTUAL lbuttondown WORD WINDOW Lbuttondown VIRTUAL lbuttonup WORD WINDOW1buttonup VIRTUAL char WORD WINDOWchar VIRTUAL defaultproc WORD WINDOWdefaultproc VIRTUAL destroy WORD WINDOWdestroy VIRTUAL make WORD WINDOWmake VIRTUAL wndproc WORD WINDOWwndproc VIRTUAL hwnd WORD 0 VIRTUAL wmessage WORD 0 VIRTUAL wparam WORD VIRTUAL lparam DWORD VIRTUAL classstyle WORD CSI YREDRAW CS_HREDRAW VIRTUAL sziconname BYTE VIRTUAL sz
16. OFFSET Exec Path Name PTR cs TSR Info TSR Exec Cmd 2 cs mov WORD PTR cs TSR_Info TSR_Exec_Flags 1 TSR_ oe ar aa mov WORD PTR cs TSR_Info TSR_Exec_ cmd _Show SW_ SHOWNOACT VATE mov WORD PTR cs TSR_Info TSR_ ID Block OFFSET My ID Block mov WORD PTR cs TSR_Info TSR_ID_Block 2 cs mov WORD PTR cs TSR Info TSR Data Block 0 mov WORD PTR cs TSR_Info TSR_Data_Block 2 0 Path of the WinApp As mentioned earlier my choice to put WINAPP EXE into a different directory is done here purely to illustrate something different In practise you would most likely have it in the same directory as the VxD However that option would introduce another small complication you would need to extract the path from the environment segment and append the filename WINAPP EXE or whatever To see more detail on a couple of those fields refer to Appendix D Hooking the vectors follows get the addr of the dos busy flag mov ah 34h int 21h z gt es bx mov dosbusyoff bx mov dosbusyseg es 336 Windows Assembly Language amp Systems Programming mov ax 352Fh get int 2F vector in ivt int 2ih i mov oldoffivt2F bx save it mov oldsegivt2F es i mov ax 252Fh shook int 2F lea dx runtime2F set ivt vector ds dx int 21h j hook any other vectors required FLAT pointer This is the nice final touch to global data finally pass the address of our global data lea dx globaldata mov
17. Ok now for the installint function DATA descrbuffer DB 8 DUP 0 offsetint DW 0 old int vector selectorint DW 0 i CODE dsselector DW O data alias to code seg hwndcs DW 0 save window handle for use in isr installint PROC no params pusha push es push ds will create alias in ldt of current task mov ax 000Ah create alias data descr for code seg push cs pop bx selector to be aliased int 31h returns ax push ax pop es mov ax hwnd mov es hwndcs ax handle of window mov ax es mov es dsselector ax alias now to get the old INT 51h vector and save it mov al 51h iget vector in idt mov ah 35h gt ES BX int 21h push es POP ax l mov offsetint bx ssave the old vector mov selectorint ax i mov dx OFFSET runtime get the new vector push cs pop ds new vector in ds dx mov al S1lh mov ah 25h set vector int 21h pop ds restore ds push ds save it again slet s hook int60 to use as old vector mov dx offsetint 262 Windows Assembly Language amp Systems Programming mov ax selectorint mov ds ax mov ax 2560h int 21h installation now finished pop ds pop es popa ret I can put the interrupt service routine in the same procedure as the install code if I wish but before listing it I want to comment on the above code To be able to get at data in the service routine I ll call it an ISR from now on I had to create a data alias that is a data selector that points to the code se
18. There are some interesting considerations from this ability to have multiple copies or instances Windows is not wasteful and only loads one copy of the code into RAM Windows will upon entry to each instance give it a unique handle but the reality is that there is just the one copy of the code For this to work each instance needs to have its own copy of the data segment or segments The downside is that your program needs to have some extra statements to handle multiple instances In practise this is fairly standardized and you can use the supplied skeleton program as the basis for much more complicated projects without having to worry about multiple instances With 32 bit applications running in Windows 95 multiple instances are treated as totally separate programs so special instance handling code is not required Opening Windows 77 Messages Event driven I introduced the basic concept of event driven back on page 7 1 intertwined with this is messages I also said that Windows sends messages to an application and the latter has to decipher them and act accordingly Let us consider this in more detail since it affects the very soul of our program Our program has to call Windows and wait for a message while waiting it is in an idle state and other tasks can be executing Windows does an incredible amount of housekeeping including receiving all of the incoming messages and parcelling them to individual queues Any
19. WINDOW lt gt mlnherits everything WINCLASSA ENDS from WINDOW WINCLASSB STRUC Ditto but a function override WINDOW lt textoutdlg gt WINCLASSB ENDS creating instances windowl WINCLASSA lt gt window2 WINCLASSB c gt window3 WINCLASSA lt gt etc CODE lea si windowl call textoutmain PASCAL parl par2 si_ call si TEXTOUT PASCAL parl1 par2 s1 ika si window2 l call textoutdlg PASCAL parl par2 s1 _ call si TEXTOUT PASCAL parl1 par2 s1 textoutmain PROC PASCAL pl p2 THIS this is the textoutmain procedure etc An object Further down in the code you would have to have the two combines procedures textoutmain and textoutdlg code and Look very carefully at the above listing First I defined a class data structure called wrinpow with a data member active and a function member TEXTOUT The latter is a pointer to a procedure called textoutmain The purists are probably very unhappy with my interspersionof the words procedure and function asthoughtheymean the same thing For ourpurposesthey do So there Most assemblers do not let you put a forward reference into a structure field It must be done when the instances are created In this example textoutmain would have to be placed in the lt gt portion of each instance declaration This is messy TASM v3 0 is the first truly object oriented assembler and has a mechanism for allowing forward referenc
20. WINDOWS ASSEMBLY LANGUAGE amp SYSTEMS PROGRAMMING 16 and 32 bit low level programming for the PC and Windows 2nd edition by Barry Kauler Lecturer Edith Cowan University M Sc EE C Eng R amp D Books Lawrence Kansas 66046 Copyright 1997 Barry Kauler All rights reserved No part of this publication may be reproduced stored in a retrieval system or transmitted in any form or by any means electronic mechanical photocopying recording or otherwise without prior written permission of the Publisher In this book many of the designations used by manufacturers and sellers to distinguish their products may be claimed as trademarks Due acknowledgement is hereby made of all legal protection Windows is a trademark of Microsoft Corporation Disclaimer Whilst due care has been taken in the preparation of this book no responsibility is accepted for any inaccuracy loss or damage to data or consequential loss or damage The content of the Companion Disk is not guaranteed to be exactly as described This edition published by R amp D Books Miller Freeman ISBN 087930474X DISTRIBUTION USA Canada Publishers Group West Publishers Group West Canada P O Box 8843 543 Richmond Street West Emeryville CA 94662 Suite 223 Tel 800 788 3123 Toronto Ontario MSV 1Y6 Fax 510 658 1834 Canada Tel 416 504 3900 Fax 4 16 504 3902 UK and Europe Asia McGraw Hill Publishing Co Longman Singapore Shoppenha
21. and EndPaint even if you dont output anything WM_ PAINT is sent if anything has happened to the window that will require its client urea to be redrawn I need a handle hDC to the client area before I can output to it paint push WORD PTR bp 14 shWnd is handle of window lea ax WORD PTR bp 42 ps far addr of paint structure push ss BeginPaint will fill the structure push ax call BEGINPAINT ReqinPaint returns handle hpc mov WORD PTR bp 146 ax hDC display context required before can output to screen push ax hdc push hOemFont call SELECTOBJECT jattaches hOemFont to hDC push WORD PTR bp 146 hDC mov ax 8 16 bit x coord push ax j mov ax 15 716 bit y coord push ax mov ax OFFSET sout far address of string to o p push ds push ax note lo half pushed 2nd mov ax 9 number of chars in string push ax call TEXTOUT push WORD PTR bp 14 hWnd lea ax WORD PTR bp 42 far addr of paint structure push ss was filled by BeginPaint push ax call ENDPAINT jmp SHORT break 106 Windows Assembly Language amp Systems Programming WM COMMAND Selection of a_ menu item will result in a WM_ COMMAND message with the 1d ntitier in wParam and zero in the low half or message lParam cmp WORD PTR bp 6 low half of lParam jne break test if a menu message Menu item If our program determines that the message is a selection WM COMMAND we find out more about it by looking at
22. check hwnd cmp si hwnd 0 Je nexist jmp endhere jis it a child this make can t handle a child needs slight mod to handle normal child window nexist cmp si hwndparent O je nochild jmp endhere nochild lea di si wndclassa call si definewndclass PASCAL di si call REGISTERCLASS PASCAL ss di mov pwindowflag 0 disable wndproc processing lea bx si szclassname lea ax si sztitlename call CREATEWINDOW PASCAL ds bx ds ax si createstylehi si createstylelo si x_coord si y_coord si wwidth si wheight si hwndparent si hmenu mainl hinstance 0 0 pwindowflag STOP Go no further Look at what I have done above Just before CREATEWINDOW I cleared pwindowf lag You must remember that this program is capable of handling multiple windows but with only one callback function Therefore the callback must be able to determine which object is associated with the window to access all the data and pointers for that window However at the moment the cart is before the Program Design 69 horse CREATEWINDOW will send some messages to the callback but I do not put the address of the object into Windows internal record until after CREATEWINDOW Exportwndproc used GETWINDOWWORD to retrieve the object address but I put it in below by using SETWINDOWWORD This latter function can only be called after CREATEWINDOW because it requires the handle that CREATEWINDO
23. fn inc tasm zi p w fn r dont append to exe x dont look in INCLUDE envir variable for incl files i slook in this path instead fn res fn re rc r x i ipath fn re COws start up lib cws Windows runtime lib cs Standard runtime import access builtin libs fn exe fn obj fn def fn res fn inc tlink sw cOws fn fn fn import cws fn def rc x i ipath fn res Note that Borland C v2 5 names the Windows library CWINS LIB while v3 0 names it CWS LIB I used the latter above The C runtime library is CS LIB which could be placed immediately after CWS if you need it Note that the S postfix designates the small model SHE He SHE SHE HE Program So thats WINASMOO MAK much the same as before The custom icon RC and DEF tiles can be the same as for previous skeletons though of course if you want to try experimenting with OOP you might like to try adding on to the RC tile Most Windows programs will want to have their own icon rather than one of the defaults and I have done this with the extended program example the one with the child control button Icon images have to be created with a special paint program I used Borlands Resource Workshop a lovely product to design my icon which I then saved as WINASMOO ICO Resource Resource Workshop then automatically added an extra line into script my WINASMOO RC tile these arbitrary
24. i return to DOSApp in another VM O we ew ew ew ew we eo we we we oe we we ax 2561h shook int 6lh in ivt dx forwarder addr of forwarder in TSR 21h dx endprog 17 point past all code in this module P compute paragraphs to keep ax 3100h terminate and stay resident 2ih ENDS begin So there you are a complete DOS TSR Note that this particular one has been written without the simplified directives which is no big deal Actually my own experience has been that it is difficult to write COM programs using the simplified directives and you are better off sticking with the long hand notation shown above You can write a TSR using EXE format and the simplified segment directives which I have done for one of the examples of Chapter 14 see also directory TSR2WIN on the Companion Disk Have a close look at what the install portion does It hooks INT 61h in the IVT then exits Because this TSR is loaded before Windows it will be in the system VM and will hook the vector in the system VM But it will also be copied to every VM Thus every time a DOS program is run within Windows Enhanced mode the new VM will have that hooked vector But what you should note in particular is that INT 61h contains the address segment offset of the forwarder code for the TSR Passing Control to the WinApp A major problem is created if our code must work for both Standard an
25. si char SHORT endx si defaultproc ret WINDOWwndproc ENDP current window object hi return flag set default 0 get message msg rec d after CreateWindow note no pascal msg if a window closed msg if Window redrawn jany selection of the menu 7a mouse msg msg that a key pressed return dx ax flag maybe I could have been a bit more impressive and emulated the case statement with a dual column table and a program loop to find a message that matches which would be better if a lot of messages are to be handled The above code is ok though 168 Windows Assembly Language amp Systems Programming MAKK Now for the part that actually creates the window herein are some secrets that make the program work By referring back to Chapters 4 and 5 you will see the code that remains from before such as RYEGISTERCLASS CREATEWINDOW SHOWWINDOW and UPDATEWINDOW The data structure WNDCLASS is there or rather an instance of it It needs to have data put into it and rather than do it in line I have called the function definewndclass to do it Compare this with the listing starting on page 112 look back there also to see how WNDCLASS is defined in WINDOWS INC The data for this structure is from the window object pointed to by SI WINDOWmake PROC PASCAL now LOCAL wndclassa WNDCLASS mov si now xor ax ax clear ax default return value does this window already exist
26. wParam and lParam The low half of Param 0 if the message is a menu selection in which case wParam contains the identifier and the high half of lParam 1 if an accelerator key has been pressed If the low half of lParam is not zero then the message is from a control such as a scrollbar and the low half of lParam the handle of the control and the high half of Param the notification code So wParam can contain the menu item identifier the control identifier or the accelerator key identifier cmp WORD PTR bp 10 IDM_QUIT wParam noquit jmp quitmessage jne noquit cmp WORD PTR bp 10 IDM_ABOUT jne break no other menu items cal epiaying a message about this program push WORD PTR bp 14 hWnd is handle Of parent mov push push mov push push mov push call Epilog code ds ax window ax OFFSET szabout far faa of string to display t d if ax OFFSET sztitle far addr of title of dialog box ds see data segment ax i ax MB_OK type of message box ax displays single ok button MESSAGEBOX Finally we have the epilog code which compliments the prolog code on page 102 At this stage BP is pointing to the saved old BP 1 which we decrement twice so it points to the saved DS which we make the top of stack and then pop to restore the original DS followed by the old BP 1 which we decrement to restore to its original value The Bare Bones 107
27. 1 byte and this is retained even for the latest Intel x86 CPUs with 32 bit or more data buses They decided to keep the 16 bit instruction pointer but it only addresses 64K and so is incompatible with a 20 bit external address bus Enter the segment The designers introduced registers called Segment registers to map the 64K region addressed by IP to anywhere in the 1M range Code could still think it was in a 64K space but transparently would be mapped to wherever the segment registers specified One tick for compatibility and one also for complexity Figure 1 7 shows how it is done 64K segment It is absolutely vital that you understand this process The 16 bit limit IP is added to the 20 bit starting address to give the 20 bit address from where the CPU will fetch the next instruction Thus the IP is an offset within the segment therefore the Segment can have a maximum size of only 64K 16 Windows Assembly Language amp Systems Programming Figure 1 7 Concept of segmentation The segment register CS is 8088 8086 CPU only 16 bits but has four binary 0 s stuck on the end 0 one hexadecimal 0 digit to provide a 20 bit starting IP address for the segment IP is added to this and thus 20 bit address is only an offset within the segment Memory up to 1M COM Executable files of COM format are restricted to 64K maximum executable as they were born back in the 8 bit CPU days however the file format
28. 3 Sea for historical reason 4 15 cel for later use CL processor type Ooh 802 re 03h 80386 04h 80486 05h FFh reserved for future Intel processors DH current value of virtual master PIC2 base interrupt DL current value of virtual slave PIC base interrupt Int 31h Function 0500h Get Free Memory Information Returns information about the amount of available physical memory linear address space and disk space for page swapping Since DPMI clients will often run in multitasking environments the information returned by this function should only be considered as advisory DPMI 1 0 clients should avoid use of this function Call with AX 0500h ES E DIe selector offset of 48 byte buffer Returns CF clear this function always succeeds and the buffer is filled with the following information Offset Length Contents 00h 4 Largest available free block in bytes 04h 4 Maximum unlocked page allocation in pages 08h 4 Maximum locked page allocation in pages OCh 4 inear address space size in pages 10h 4 Total number of unlocked pages 4h 4 Total number of free pages 18h 4 Total number of physical pages ICh 4 Free linear address space in 20h 4 Size of paging tile partition in pages 24h OCh Reserved all bytes set to OFFh Int 31h Function 0501h Allocate Memory Block Allocates and commits a block of linear memory Call with AX 0501h BX CX size of block bytes must be nonze
29. 41 42 209 300 244 300 336 234 220 138 71 19 21 26 209 209 209 209 209 2 209 GETKBCODEPAGE GETKEYBOARDSTATE GETKEYNAMETEXT GETKEYSTATE GETMESSAGE GETMODULEHANDLE GETNUMTASKS GETPROCADDRESS GetProcAddress32W GETSELECTORBASE GETSELECTORLIMIT GETSTOCKOBJECT GETSYSTEMDEBUGSTATE GETSYSTEMMSECCOUNT GETWINDEBUGINFO Q Global data via a DOS TSR Global Descriptor Table Global labels GLOBALDOSALLOC GLOBALENTRYHANDLE GLOBALENTRYMODULE GLOBALFIRST GLOBALFIX GLOBALHANDLE GLOBALHANDLETOSEL GLOBALINFO GLOBALNEXT GLOBALPAGELOCK GLOBALWIRE GOOFEE diagrams Grabber functions H Handle HARDWARE EVENT Heap32First Heap32ListFirst Heap32Next Hexadecimal High memory segment HMEMCOPY hPrevInstance Hungarian convention hWnd I I O address space I O ports VO privilege IOPL field IO SYS Icon custom IDIV instruction IDT IDT redirection to IVT Immediate addressing mode IMUL instruction IN and OUT instructions In line assembly 209 210 210 210 79 234 210 234 220 210 210 210 210 217 210 275 337 19 120 210 213 213 213 211 211 213 213 213 211 218 INC instruction Include files Indexed addressing mode Inheritance INITAPPQ Initialisation INITTASKO INQUIRESYSTEM Instances Instruction size prefix Instructions INT instruction INT 9 INT 1 Oh INT 15h INT 15h AH 88h AH 87h INT 15h AH 89h I
30. Although a parameter is passed to TEXTOUTQ I havent used it within the assembly routine I put it in to show that it is an option Note that the compiler will give a warning at least Borlands BCC compiler does that the passed parameter is unused In Line Dos and Don ts While we are on the topic of in line assembly I might as well cover the major do and donts Ive grouped these below for easy reference 150 Windows Assembly Language amp Systems Programming e The asm keyword differs for different compilers Borland C will accept asm and the latest version accepts _asm for compatibility with Microsofts C C e Notice in the example that I chose to use the asm keyword at the start of every line rather than use the opening and closing braces I prefer doing it this way because the in line assembler cannot define code labels at least Borland s C C cant By using the keyword on every line at the termination of each line the compiler regains control and a label is allowed For example asm je placel asm nop placel asm mov ax vall e You have complete access to all data and code labels in the C program barring the usual C constraints e Note that the compiler saves and restores some CPU registers upon entry and exit from an in line assembly section Compilers differ in what they save and restore e You cannot use the semicolon to start a comment Instead you have to use the standard C deli
31. One very interesting possibility that you can see in Figure 15 5 is that Layout can generate DLL output That is any program that you construct inside Layout can simply by selecting Make blackbox from the menu generate a DLL DLLs are mighty handy because they can readily be used by various development environments including LabView Because Layout is a totally open environment with no run time distribution licencing required unlike LabView you might find it useful as an adjunct for use with LabView Layout was developed in the USA by VTools Inc formerly Objects Inc and their Web page is http www vtools com Advanced Systems Programming 367 Assembly versus High Level Languages My vision of the viability of programming at two extremes is an interesting diversion but for many people the argument is more focused The current fight that has been going on for some years is between languages such as C and assembly C and C is winning but I would like to put in my two cents worth Gloves Always the debate rages about the applicability of assembly Off language in our modern programming world An excellent and balanced argument is to be found in the article Assembly Language Lives by Michael Abrash Dr Dobb s Journal March 1990 It is several years old but still relevant Faster The simple bottom line truth is that assembly language produces smaller far faster and smaller code than compilers
32. Prevents the memory block from moving in linear memory You would use this in Standard mode to lock a block in place Complement is GLOBALFREE WOWGetVDMPointerFix e GLOBALHANDLE Supplies a selector and returns a handle to the memory block e GLOBALPAGELOCK Prevents a segment from being paged out or moved You can use this in Enhanced mode to guarantee a segment will be present at all times Locks the segment at a physical address Complement is GLOBALPAGEUNLOCK VirtualLock e GLOBALWIRE Im not sure what this one does it seems to be similar to GLOBALFIX BIOS DOS Windows Services 21 1 HARDWARE EVENT Available in Windows 3 1 only Places a hardware related message into the system queue HMEMCOPY Available with Windows 3 1 only Copies a block of data from one address to another LOADMODULE Executes a separate application Supported but recommend CreateProcess LOCKINPUT Available in Windows 3 1 only Locks and unlocks input to all tasks except the current one LOCKSEGMENT Locks a segment in memory Its complement is UNLOCKSEGMENT NETBIOSCALL Issues a NetBIOS INT 5Ch interrupt OUTPUTDEBUGSTIUNG Sends a debugging message to the debugger if present or to the AUX device if the debugger not present PEEKMESSAGE Checks the application message queue without waiting PBESTOCHANGOSELECTOR Described in the SDK 3 1 Same as CHANGESELECTOR documented in SDK 3 0 Obtains an alias to a code or d
33. RET 10 causes RET to add 10 to SP after popping the return address effectively dumping all parameters as required for the Pascal convention break sub ax ax returns 0 in DX AX callback functions cwd jreturn a 32 bit long value return dec bp final Standard manipulation of regs dec bp mov sp bp it is called the epilog code pop ds i pop bp dec bp ret removes parameters SKELETONPROC ENDP o ooo a a CEEE Simplified I showed earlier that there is a simplified alternative for the prolog epilog code code The matching epilog is similarly simple pop ds epilog POP _b retf 1 So here again refer to Figure 3 1 to see what it looks like Clicking on the File menu item pops down two selections Quit and Message Selecting the latter results in a message box looking very much like that shown on page 172 High Level Assembly What s in this chapter Equates Preamble What I have for vou in this chanter is the same program from the previous chapter page 94 but wow is it smaller bne thing you will have noticed from that first program is that it does an incredible amount of stack manipulation this makes the program both long and very tedious to write The Borland and Microsoft plus other vendors assemblers have some high level features that ease the coding burden considerably even to the point of the program being as short as the equivalent written in C or some other high lev
34. See Chapter 5 for an explanation of INVOKE TASM version 5 has PROCDESC that does the same job as INVOKE see Chapter 13 EXTRN INITAPP FAR EXTRN INITTASK FAR EXTRN WAITEVENT FAR EXTRN DOS3CALL FAR EXTRN UPDATEWINDOW FAR EXTRN BEGINPAINT FAR EXTRN ENDPAINT FAR EXTRN DEFWINDOWPROC FAR EXTRN POSTQUITMESSAGE FAR EXTRN REGISTERCLASS FAR EXTRN GETSTOCKOBJECT FAR EXTRN CREATEWINDOW FAR EXTRN SHOWWINDOW FAR EXTRN GETMESSAGE FAR EXTRN LOADCURSOR FAR EXTRN TRANSLATEMESSAGE FAR EXTRN DISPATCHMESSAGE FAR EXTRN LOADICON FAR EXTRN TEXTOUT FAR EXTRN MESSAGEBOX FAR EXTRN SELECTOBJECT FAR Below is the data segment Here we define all of the variables strings and arrays that the program will use DATA This must be at beginning of data segment DWORD 0 Windows reserved data space rsrvptrs WORD maxRsrvPtrs 16 bytes at top of DATA seg WORD maxRsrvPtrs DUP 0 Do not alter hPrev WORD 0 Space to save WinMain parameters hInst WORD 0 lpszCmd DWORD 0 cmdShow WORD 0 i DATA szwintitle DB SKELETON PROGRAM 0 szskeletonname DB SKELETON 0 hOemFont DW 0 handle to OEM font sout DB Hi there szabout DB Assembly Language Skeleton O messagebox sztitle DB Barry Kauler 0 ee 96 Windows Assembly Language amp Systems Programming Startup Code The startup code is fascinating because it is something you normally dont see in a Windows program It is the code that is first entered when th
35. The 386 does provide a mechanism for going to a more privileged ring called a gate of which there are call gates interrupt gates task gates and trap gates However only code in ring 0 is supposed to be able to create such gates I kind of glossed over this little detail in an earlier discussion look back at Figure 11 1 but the interrupt services are at ring 0 so the entries in the interrupt descriptor table IDT of the form selector offset reference an interrupt gate not a descriptor An interrupt gate or any gate for that matter sits in the LDT or GDT as an 8 byte entry just like any other descriptor see Figure 12 1 but it has a different format In the case of interrupt handling if there is to be a ring transition i e if the ISR is at a more privileged level than 3 then the entry in the IDT is not a descriptor it is an interrupt gate However the code descriptor for the ISR is still there at another entry also in the IDT I presume A call gate is the mechanism for a CALL instruction to call code at a more privileged level It works just like the interrupt gate in which the descriptor in the LDT or GDT of the code to be called is not called directly Instead you call a call gate which in turn calls the more privileged code via its descriptor Call Gate Structure Pll postulate that you want to call some ring O0 code at some address say 0907 0000 How you would get the selector of some ring O code is another
36. Thus the linear address range from 0 to 4 3G is addressable Ring 3 32 bit WinApps use a code segment selector of 13Fh and data segment selector of well I dont want to gurantee that it will always be the same You can look at the segments using a debugger anda DPMI f Service Mapping between system VM and DOS VMs Advanced Systems Programming 347 The same selector value is loaded into DS ES FS and GS and it is extremely interesting that the type of selector has the expand down limit of 1M that is must be greater than 1M This prevents data accesses into the first 1M of linear memory that maps in the DOS VM The above description of linear addresses that map to physical are not the only method for getting at physical memory from Protected mode There is a DPMI function that performs mapping between a linear address and a physical address function 0800h Physical Address Mapping You supply it with a 32 bit physical address and it will give you a 32 bit linear address You could then use function 0007h Set Segment Base Address to put the linear address into a descriptor Of course the descriptor would have to have been previously created for example by function 0000h Curiously function 0800h is not recommended for addressing below physical 1M I presume because there are other DPMI functions for that purpose Windows does set aside other parts of the linear address space for special purpos
37. Windows Standard Mode Hardware one serere 258 Interrupt Handler Code ssesssssssesereresserrerses 260 Enhanced Mode Hardware Interrupts 263 Direct Memory ACCESS sssrereserrererrrrerseeres 264 Real Mode Access 267 viii Ch Page Preamble osnenseesereresesererrresereererreerree 267 Accessing Real Mode from Protected Mode 268 Accessing Real Mode via the IVT 5 000 269 Virtual Machines ccc eee e eee eee eens 271 DOS TSRS usaron essen tigen ee Saha 273 Accessing Protected Mode from Real Mode 275 Signalling a WinApp from a DOSApp 276 Passing Control to the WinApp see seers 278 The DOSApp Signaller esses eee eee e ees 280 Hooking a Real Mode Interrupt from a WinApp 283 12 32 Bit Ring 0 287 Preamble ccccec cece cece eee eeene reset eeeaseaeeaes 287 16 and 32 Bit Programming seee eee e eens 288 Ring Transition Mechanism seee eee ee eens 291 Call Gate Structure cc cece eee e rene eee eens 292 Ring Transition Example Code 5 294 FLAT Memory cece eee c eee e cere e ence ene en nets 300 Moving On cece eee renee eee ene t enn n eres 305 13 32 Bit Ring 3 307 Preamble eiccs casters tati e oo i E eee eee eNews 307 TASMS versus MASM6 0c cee eee ence eens 308 Installing TASMS 000 cee e eee tee eee ee eens 309
38. amp Systems Programming Descript Call with Returns o Int31h Function 0101h Free DOS Memory Block Frees a memory block that was previously allocated with the Allocate DOS Memory Block function Int 3 1 h Function 01 00h Call with AX O1Olh DX selector of block to be freed Returns if function successful CF clear if function unsuccessful CF set AX error code 0007h memory control blocks damaged also returned by DPMI 0 9 hosts 0009h incorrect memory segment specified also returned by DPMI 0 9 hosts 8022h invalid selector Int 31h Function 010th Resize DOS Memory Block Changes the size of a memory block that was previously allocated with the Allocate DOS Memory Block function int 31h Function 0100h Call with AX 0102h BX new block size in 1 6 byte paragraphs DX selector of block to modify Returns if functions successful CF clear if function unsuccessful CF set AX error code 0007h memory control blocks damaged also returned by DPMI 0 9 hosts 0008h insufficient memory also returned by DPMI 0 9 hosts 0009h incorrect memory segment specified also returned by DPMI 0 9 hosts 8011 h descriptor unavailable 8022h invalid selector maximum possible block size paragraphs Int 31h Function 0200h iGet Real Mode Interrupt Vector JReturns the contents of the current virtual imachine s Real mode interrupt vector for the specified inte
39. amp Systems Programming dsl DW 0 fsl DW 0 gsl DW 0 ipl DW 0 csl DW 0 spl DW ssl DW 0 regstruc ENDS CODE callreal PROC PASCAL NEAR LOCAL regl regstruc USES ax bx 6 hye Ss Ly i push ss pop es setup ES DI point to data struc lea di regl mov WORD PTR di eax1 0500h 5 into ah mov WORD PTR di ecx1 0007h 07 beep mov bx 0016h int to call mov cCx O mov ax 0300h simulate Real mode int int 31h jc error mov ah 0O get char from key buffer int 16h returns in ax will hang if no char in buff mov dl al char in dl mov ah 2 display a char int 21h rert INT 31h Inte s DPMI specification does place some caveats upon the AX 03001 0300h function The CS IP in the Real mode register data structure is ignored by this function The appropriate interrupt handler based upon the value passed in BL will be called If the SS SP fields in the Real mode register data structure are zero a Real mode stack will be provided by the DPMI host Otherwise the Real mode SS SP will be set to the specified values before the interrupt handler is called The flags specified in the Real mode register data structure will be pushed on the Real mode stack s IRET frame The interrupt handler will be called with the interrupt and trace flags clear Values placed in the segment register positions of the data structure must be valid for Real mode i e the values must be paragraph addresses and not selectors All general register fie
40. and hence hardware interrupts still go to the IDT in the current VM note the emphasis on current Because the DOS VM is supposed to behave in all respects like an XT model PC the interrupt will eventually come down to the IVT INT 51h POSTMES SAGE A skeleton hardware interrupt handler Real Time Events 259 countries it s all the rage However the following is extremely interesting and I ve put it in for the education it gives us about the warp and weave of interrupt handling What I have for you here is a useful program that hooks INT 9 the keyboard hardware interrupt except to illustrate how Standard mode works I have hooked INT 5 1h This keyboard hook can be very useful for filtering whatever comes from the keyboard before Windows has a chance to see it Note that INT 5lh is invoked every time a key is pressed or released with bit 7 of the scancode distinguishing which Hardware interrupts are somewhat more delicate than their software cousins for example you can t call Windows functions from them with one exception POSTMESSAGE Microsoft especially made sure that this would work from the hardware interrupt level so that a hardware interrupt service routine can signal a Windows application There is a particular problem with these hardware interrupts due to the way they are mapped With Windows in Standard mode I have shown on the previous pages that the keyboard interrupt maps to INT 5
41. but I guess thats too simple Undefined_Device_ID is an equate to a special number for VxDs that dont have an ID I could have put Undefined _Init_Order equate for the last parameter but I wanted to make sure the printer ports got hooked by my VxD before any other The lower the number the earlier the initialisation and VMM_Init Order equates to zero so it gets in first Notice that there are two commas after the last parameter This is because there can be two more parameters These can specify routines for V86 and Protected mode access Sixteen bit applications can call INT 2Fh function 1684h to get access to these routines However INT 2Fh assumes a 16 bit program is running so 32 bit applications cannot access these functions Its awful I know but such is the legacy of backwards compatibility Therefore Microsoft was forced to provide a different mechanism for calling services in a VxD from a 32 bit WinApp see the DeviceloControl function introduced in Chapter 8 The alternative is that a 32 bit application can thunk down to 16 bits Also look at the technique described on page 350 local data VxD _LOCKED _DATA SEG Device Name DB VDEMOD 0 354 Windows Assembly Language amp Systems Programming VDEMOD_ Owner DD VXxD_LOCKED_DATA_ENDS Pe O ee ee eS So E E a initilisation code VxD_ICODE_SEG BeginProc VDEMOD_Device_Init beep push eax mov al OB6h turn on loudspeaker out 43h al
42. et or cleared j it is only necessary to switch VM s if Enhanced mode mov al winmode and al l set if Enhanced jz Enhanced Standard see Companion Disk Real Mode Access 281 jmp doneit Enhanced see if forwarder TSR is present by checking interrupt vector 61h mov ax 3561h sget int 6lh vector address int 21h gt es bx mov ivt6 loff bx Ssave it mov ivt61lseg es mov ax es be sure there is one or ax bx mov tsrloaded ax set if TSR loaded jz cantcall if not complain and quit use2F 1685h to switch to system virtual machine and call forwarder program in the DOS TSR cmp tsrloaded 0 jz dontswitch mov ax 1685h switch VM s and execute mov di bx es di callback addr int 61 hndlr mov bx 1 bx VM to switch to system VM mov cx 3 cx 3 wait until interrupts enabled sand critical section unowned xor dx dx dx si priority boost 0 xor si si int 2Fh switch to system VM and do INT 60 dontswitch doneit Ul DOSApp continues f This program or any DOS application with this code in it looks at the INT 6lh vector to see if there is anything in it there will be O if not hooked If so the program goes ahead and calls the forwarder portion of DOSTSR COM the DOS TSR However this is where you need to think If you loaded the TSR from the DOS prompt before loading Windows in contrast to loading it from WINSTART BAT
43. high level language In the first half of this chapter I introduced objects and some details about the inner working of C and how to interface to it now applying 00 techniques brings an assembly language skeleton program down to just nine lines OOP and assembly language go together in a most natural way with the result that coding becomes a breeze Here is an 00 skeleton program WINASMOO ASM gt WINASMOO EXE INCLUDE WINDOWS INC INCLUDEWINASMOO INC DATA windowl WINDOW CODE kickstart lea si windowl jaddr of window object call si make PASCAL si make the window ret END There are eleven lines there but take off the comment line and put the code label on the same line as the following instruction and it becomes nine lines This program is the most basic skeleton putting only a window on the screen and nothing else In a moment I ll show you how simple it is to add the menu bar and message box as per skeletons from previous chapters But first have a look at the above Kickstat In the data segment I created an instance of a WINDOW structure called windowl Inthe code routine called kickstart I set THIS to windowl and then called make which as its name suggests creates the window and puts it on the screen 1 54 Windows Assembly Language amp Systems Programming Hiding the fed tape Simple C classes for Windows You may have noticed that the syntax for creating the instance of W
44. is any number from 0 to 255 Note that some of those numbers will also correspond to hardware interrupts which means that such interrupts can be called either by a hardware event or from a program Real Time Events 251 Exceptions Yet another class of interrupts is exceptions generated by the CPU Invocation of the hooked interrupt either software or hardware will result in transfer of execution to the TSR This happens immediately The TSR terminates with an IRET instruction which sends control back to whatever was running before the interrupt Hooking a Vector What I have done in the first part of this chapter is put together a program that hooks INT 16h The new INT 16h service routine uses the music code from page 246 so there is audible feedback of it executing Once the service routine is installed INT 16h can then be executed from anywhere including another program and the service routine will be invoked TSR The program can be any basic skeleton to which you patch the installation following code The install portion could be wherever you want routine it in WinMain in kickstart 00 program or in the callback You could start the program up as an icon or invisible and immediately execute the install code This is what the install code would have to be DATA offsetint DW 0 sold int vector selectorint DW 0 i CODE install PROC PASCAL NEAR no params USES ax bx cx dx si di es mov al 16h get vec
45. it cant There is a problem with syntax WINDOWS H has a syntax designed to be understood by the C compiler and this is mostly gibberish to the assembler however Microsoft introduced with version 6 0 of their Macro assembler MASM and Borland with C v3 0 a H to INC translator Note the convention that all C syntax Include files have the extension H Instead of WINDOWS H in assembly we use WINDOWS INC which is supplied by Borland and Microsoft Note the convention that Include files for assembly language have the extension INC though I cant vouch for this for all software vendors The listing starts on the next page and as you look through it you will see how I have included WINDOWS INC and how I have accessed the structures There are some example extracts from WINDOWS INC to clarify the explanation The first listing is designed around Borland TASM version 2 5 so once again I am aiming for the earliest possible version If you only have MASM version 5 1 or earlier or TASM prior to version 2 5 which do not have the necessary high level constructs you can only assemble the Windows program from the previous chapter For further discussion of version numbers see page 88 If you want to make use of the latest features for writing streamlined code especially if writing for Win32 then the later the version the better Complete MASM amp TASM skeleton listings for all versions High Level Assembly 1 It is
46. prolog and epilog required for a callback function Refer back to page 103 for the prolog code and page 107 for the epilog code MASM v6 achieves the same thing with a different syntax while 32 bit programming uses the STDCALL language qualifier and doesnt need further qualification Figure 5 1 shows the stack upon entry to the callback function Now for the case logic that processes the messages mov ax msgtype get message type cmp ax WM_CREATE msg received after je xcreate CreateWindow func is called emp ax WM_DESTROY ymessage if a window is closed je xquitmessage emp ax WM_PAINT msg if Windows has already redrawn any part of the window due to size change for example je xpaint cmp ax WM COMMAND any selection of the menu will jne notwmcommand produce this message Mm xmenu notwmcommand cmp ax WM_LBUTTONDOWN one of many mouse jne notwmlbutton messages jmp xbreak notwmlbutton cmp ax WM_CHAR ymessage that a key pressed je xchar Default handling of messages call DEFWINDOWPROC PASCAL hWnd msgtype wParam lParam jmp xreturn Back to Windows which will in turn xcreate return to after DispatchMessage Now to process the messages call GETSTOCKOBJECT PASCAL OEM_FIXED FONT High Level Assembly 119 mov hOemFont ax handle to font jmp xbreak xquitmessage call POSTQUITMESSAGE PASCAL 0 jmp xbreak xchar jmp xbreak xpaint lea ax s3 ps far addr of paint struc
47. see quotation on page 198 In a virtual machine other than the system virtual machine see page 274 there should not be any conflict with Windows memory management and you can use all the DPMI services Microsoft sanction this statement Ive done the right thing and printed Microsofts discouragement for extensive use of DPMI Code that you will see in subsequent chapters has been tested in both Standard and Enhanced modes but with a book of this nature I do have to insist on a total disclaimer of any liability You use the code with this understanding 200 Windows Assembly Language amp Systems Programming Windows95 Most of my code has also been tested under Windows 95 and works However this statement is true of 16 bit applications running in Windows 95 native 32 bit applications are somewhat more restricted There are work arounds For example many of the low level API functions are available as 32 bit versions but are not supported by the import library during linking nor are they documented However we can still use them refer page 235 One problem is that you cant just call 16 bit functions such as the 16 bit API functions from 32 bit code Most of the interrupt routines also assume that the caller is 16 bit code Standard DOS Interrupts Microsoft implies from their Developers Notes that most of the DOS services will work ok when called from a Windows program running in 16 bit Protected mode Those spec
48. though to execute Real mode code you must perform the necessary DPMI function to transfer the CPU to Real mode and vice versa Sharing memory between 16 and 32 bit WinApps All 16 and 32 bit Winapps reside in the System VM and use the same LDT Also the pages tables map the linear addresses below 1M to the same physical memory These two facts hold for Windows 3 x and 95 which means that a memory block below 1M is global Windows 95 32 bit applications have mechanisms for sharing memory such as memory mapped tiles see Chapter 8 but memory global to all 16 and 32 bit WinApps requires a less unofficial solution A solution based upon the above two facts is on the Companion Disk in directory SHAREALL A 16 bit WinApp establishes the global area which can be freely accessed by other WinApps and can also be shared between 32 bit WinApps Note however that the WinApps must supply their own protocols for mutual exclusion I have used this technique to export a data selector to the data segment of GOOFEE EXE my CASE tool bundled with another book written by me see page 359 This allows other WinApps to directly control GOOFEE EXE There are protocols to govern the communication A description of GOOFEE EXE and the mechanism for external control is to be found at http www goofee com Advanced Systems Programming 351 Anatomy of a VxD Changing the subject somewhat VxDs are Microsoft preferred direction for access
49. v7 0 and later is bundled with elements of the SDK Actually the main reason that you require the SDK is for the programs RC EXE the import file LIBW LIB and Windows compatible LINK The SDK does have some other tools such as a debug version of Windows but most of these tools are available with recent compilers There are also a lot of useful manuals with the SDK Microsoft has gone away from supplying printed manuals and wherever I refer to a Microsoft manual in this book it will be on line although in most cases it should also be available for purchase separately I personally prefer printed manuals If such housekeeping i e the correct installation of all the software tools is too much trouble get together all the above files or suitable equivalents and put them all into the same directory Problem solved Look ahead through this book and youll see examples of Make files for both Microsoft and Borland 58 Windows Assembly Language amp Systems Programming Legacy chapter Microsoft and Borland version notes TASM v2 5 Microsoft Quick assembler I must emphasize again that this chapter is a legacy chapter I am using the oldest tools and the most primitive assembly language skeleton This is not what I recommend for actual development but the very basic skeleton is excellent for learning I have included all of the meandering through version numbers below partly to record what I remember b
50. would call this if your current VM isnt doing anything and you want to try and improve efficiency by releasing it Issues involved Advanced Systems Programming 349 e INT 2F AX 168th 1682h Function 168 1h tells Windows not to switch VMs whereas 1682h says go ahead If your code is going into a critical section and must not be interrupted then use these two Note however that hardware interrupts still do happen e INT 2F AX 1684h Function 1684h gets an address for calling a VDD and getting information from it The VDD ID is passed via BX and the function returns the Real mode address in ES DI If it returns NULL the VDD does not provide Real mode services The Windows INT 2Fh Relationship To get a deeper feel for INT 2Fh and its relationship with Windows I have placed a program on the Companion Disk that monitors all INT 2Fh Real mode calls via the IVT and logs them to either the printer or screen The traffic over this interface is fascinating INT 2Fh is Windows main method for letting DOS device drivers know what is going on and vice versa Windows can let drivers know when and how it is loading and unloading and DOS drivers can tell Windows the address of their Protected mode code Also virtual drivers communicate with DOS drivers over this highway What I suggest is rather than me printing out the results of my INT 2Fh monitor program try it for yourself It is a TSR that you load from the DOS prompt an
51. 237 and above I suggested the relatively complicated approach of writing directly to the video RAM which will also involve manipulation of I O registers on the adaptor card However there is another way the BIOS and DOS services These services will do whatever you want What I have listed below is a complete program that is an extension of the 00 program with a control button developed in Chapter 6 Clicking on the button causes another window to appear but this window is different It is a pseudo text mode window that uses the IBM graphics character set not ANSI characters See Appendix B Furthermore this window always remains visible no matter what you do this window will always appear until the application is terminated The most fascinating aspect of this program is that it uses the plain vanilla BIOS and DOS video services to generate this window without the least complaint from Windows This window is your own personal possession as far as Windows is concerned it doesnt exist Yet I have arranged the program so that Windows can never overwrite it unless you want it to I have listed this program here and it is also on the Companion Disk in directory DPMIO as a source of ideas possible building blocks for other more wondrous programs Ok here it is This demo program is written in TASM v3 0 It uses the WINASMOO INC OO file developed in Chapter 7 240 Windows Assembly Language amp Systems Pro
52. 286 but you ll find them enhanced plus many new ones Note that I ve put a summary in Appendix A showing which instructions work on the 86 286 and 386 Once you start to code explicitly for the 386 beware that there is no turning back your program won t run on the 86 or 286 Most important of all incompatible enhancements is the removal of the 64K segment limitation by means of EIP to access the code segment ESP to point to the top of stack and the various other general and data segment addressing registers EBX ESI EDI etc mov AL ES BX 16 bit index mov AL ES EBX 32 bit index 24 Windows Assembly Language amp Systems Programming Figure 1 11 Registers of the 386 386 CPU General Pa ees Registers 31 15 PURPOSE Accumulator general use Base general indexing Count general string Data general Source Index EDI DI _ Destination Index Base Pointer stack Stack Pointer stack Segment Registers 15 0 PURPOSE Shadow reqister Code selector ips Shadow reqister Data selector sso Shadow register Stack selector Shadow register Extra selector FS _ Shadow register selector ics Shadow register selector Instruction Pointer and Flags 31 15 0 31 15 0 EFLAGS FLAGS em Segment Address Registers 23 0 PURPOSE re register Address of the GDT IDT register Address of the IDT 15 TSS segm t selector LDT segm t selector Control CR0 3 Debug DRO 7
53. AX error code 802 1 h invalid value access rights type bytes invalid 8022h invalid selector 8025h invalid linear address changing the access rights type bytes would cause the descriptor to reference a linear address range outside that allowed for DPMI clients Int 31h Function 000Ah Create Alias Descriptor Creates a new LDT data descriptor that has the same base and limit as the specified descriptor Call with AX OOOAh BX selector Returns if function successul CF clear AX date selector alias if function unsuccessful CF set AX error code 801 h descriptor unavailable 8022h invalid selector Int 31h Function OOOBh Get Descriptor Copies the local descriptor table LDT entry for the specified selector into an S byte buffer Call with AX OOOBh BX selector ES E DI selector offset of 8 byte buffer Returns if function successful CF clear and buffer pointed to by ES E DI contains descriptor if function unsuccessful CF et AX error code 8022h invalid selector Int 31h Function 000Ch Set Descriptor Copies the contents of an 8 byte buffer into the LDT descriptor for the specified selector Call with AX 000Ch BX selector EX E DI selector offset of 8 byte buffer containing descriptor Returns if function successful CF clear if function unsucessful set AX error code 8021 h invalid value access rights types byte invalid 8022h invalid
54. As described in the last chapter putting 32 bit instructions into a 16 bit segment incurs only a small instruction prefix penalty Putting 32 bit segments into a 16 bit application can also be done Considering these points many developers do not feel any urgency to go totally 32 bit However if you want to move ahead and write a true native 32 bit application this is the chapter 307 308 Windows Assembly Language amp Systems Programming TASM 32 bit support Porting code from MASM to TASM lfemising the differences between MASM6 and TASM5 TASMS versus MASM6 Back in Chapter 5 I compared the features of the various versions of TASM and MASM targeting 16 bit applications The two products have tended to leap frog each other but MASM has remained stuck on version 6 11 for some time now Borland has recently released version 5 0 which does not leap frog MASM it only brings it to about even QUESTION How many Microsoft Officials does it take to change a light bulb ANSWER None They will just declare darkness to be the new standard Not so far from the truth Microsoft has put MASM on the back burner for some time because it is a very small fish for them At the time of writing rumour is that they are selling it to another company Borland to their credit does not consider itself to be too big to ignore the lower end of the market That is the relatively small volume sellers like assemblers
55. Assume also that it requires two parameters Yes this will work or at least will get execution to the TEXTOUT routine but there are other factors to consider e THIS e Polymorphism THIS is a keyword in Borland assembly language and C It is just an equate THIS address of current object Borland C often uses the SI register to hold THIS Generally an object pointer points to the current object or whatever object we wish to deal with A little note on the side that will help as you study this chapter The use of SI to hold THIS applies to 16 bit code For 32 bit code it becomes ESI Quite simple In general convert any examples in this chapter to 32 bit code by prefixing the registers with E Any reference to FAR pointers may not be relevant because the 32 bit addressing can address the whole 4 3G with just the offset Also when writing 32 bit Windows applications use the STDCALL language qualifier see MODEL on page 111 not PASCAL STDCALL convention is that parameters are pushed right to left with stack cleanup in the called function 140 Windows Assembly Language amp Systems Programming Polymorphism means that TEXTOUT can in fact be many different routines all with the same name At this point some code will help DATA WINDOW STRUC active DB 0 example data member TEXTOUT DW textoutmain example function member WINDOW ENDS WINCLASSA STRUC sub class of WINDOW
56. Base of a number BEGINPAINT Binary coded decimal Binary numbers Binding assembly language Binding early Binding late BIOS amp DOS services BIOS extensions BIOS ROM Boot Record Bootstrap program Bus CPU Byte addressing C C binding C interfacing with CALL RET Call gate Call gate creation of Callback function CALLMSGFILTER CallProce32W CATCH CHANGESELECTOR 413 44 181 208 208 208 208 54 94 81 94 50 147 150 123 367 148 145 367 62 330 105 145 141 142 4 195 189 1 179 142 147 38 40 292 296 79 102 208 220 208 208 414 Windows Assembly Language amp Systems Programming Class CLASSFIRSTQ CLASSNEXT CLI instruction Client area CMACROS INC CMP instruction CMPSx instructions Code amp data labels Code descriptor Code labels COMM driver functions COMMAND COM Command Line tail Compiling C to ASM O P CONFIG SYS Control bus Control class Conventional amp extended memory CPU architecture CPU registers CPU 8 bit CREATESYSTEMTIMER CreateToolhelp32Snapshot CREATEWINDOW D DAA instruction DAS instruction Data bus Data encapsulation Data labels Data types DB Define Byte DD Define Doubleword DEATH DEBUG EXE DEBUGBREAK Q DEBUGOUTPUT DEC instruction Default message handling DEFHOOKPROC Definition file DEFWINDOWPROC Descriptor DESTROY message Development cycle DeviceloControl Direc
57. Bit Ring 0 301 use a selector the linear address contained in the descriptor can change and it is of no concern to you GLOBALPAGELOCK keeps it fixed and also ensures that the pages remain in memory which would be optimal for interrupt handlers There is another API function that you might like to consider if your requirement is only that the linear address remains unchanged and paging is ok If paging is left on as per normal the only repercussion is a possible access delay unless you are doing coding that involves talking to specific physical locations Consider another alternative GLOBALFIXQ which fixes a segment at a fixed linear address but allows paging out Getting Back to the central argument The objective now is for our ring O addressability 32 bit procedure to be able to call VMM and VxD functions The to FLAT ring 0 following code is a re do of MAKERINGOSELECTOR which code sets up addressability to ring 0 makering0selector PROC get addressability of ringO ringOfunc invoke GLOBALPAGELOCK cs cmp ax 0 je lockfailed lea si ms_dos_str mov ax 168Ah get dpmi extensions entry point int 2Fh gt es di undocumented altel cmp al 0 Oeeoe pee jne extensionsnotfnd mov WORD PTR dpmiproc di save entry point mov WORD PTR dpmiproc 2 es mov ax 100h undocumented call dpmiproc sax selector to ldt iC extensionsnotfnd mov ltdt selector ax mov 8 ax find the linear address of CS
58. Dynamically Loadable Drivers The ability to open a virtual device driver at any time is related to the new capability of Windows 95 to support dynamic loading CreateFile loads a driver and CloseHandle unloads it Threads A Windows process is an application be it a Windows application or a DOS Virtual Machine VM However 32 bit Windows 95 applications can also have multiple threads of execution and the thread becomes the basic unit that can be scheduled by the operating system With Windows 3 x the System VM running all the Windows applications and the DOS VMs each running a DOS application are preemptively scheduled while the Windows applications themselves are cooperatively scheduled i e amongst themselves Windows 95 adds to this picture with 32 bit applications that have one or more threads that can be preemptively scheduled Because scheduling is thread based the term process is awkward the 16 bit applications become one thread and each DOS VM is one thread Here are all the Windows 95 thread and process related functions AttachThreadInput CommandLineToArgvW CreateProcess CreateRemoteThread CreateThread ExitProcess ExitThread FreeEnvironmentStrings GetCommandLine GetCurrentProcess GetCurrentProcessId GetCurrentThread GetCurrentThreadId GetEnvironmentStrings GetEnvironmentVariable GetExitCodeProcess GetExitCodeThread GetPriorityClass GetProcessA ffinityMask GetProcessShutdownParameters
59. Enhanced mode does not When to There are Windows functions that overlap DPMI services but use DPMI most of the latter are undocumented and in the light of the above services comments from Microsoft we are left between a rock and a hard place Andrew Schulman PC M agazine Jan 28 1992 page 323 puts it this way Youre stuck with using either DPMI INT 31h functions which Intel documents but Microsoft doesnt sanction or Windows KERNEL functions which Microsoft doesnt document What a choice Newly Windows 3 1 does make some of the previously undocumented Sanctioned functions official by documenting them in the SDK and also functions introduces some new low level functions many of which cannot be used with Windows 3 0 Since there are going to be a some 7 users out there still using 3 0 I have been careful in this chapter to clarify which functions are not backwards compatible Microsoft has put some functions into a library TOOLHELP DLL that you can bundle with your application for backwards compatibility with Windows 3 O Restrictions A final note is that other programmers have commented in the On using press and it is my own empirical experience that the DPMI DPMI services work under Windows Ive tried most of them but not all The main thing to be careful about is using those DPMI services that might conflict with Windows management of the memory such as allocation of memory blocks
60. FFFF But Protected mode in the same VM when addressing this same range of linear addresses also maps to the same physical addresses This may be a somewhat esoteric point and so may not be something to be concerned about However I have thrown in this clarification in case the conceptual conflict has arisen in your mind In fact you can also access that same physical address range at Protected mode linear addresses somewhere above 8100 0000 mentioned above The Windows DOS DPMI Relationship This section develops further the relationship between DOS and windows What are the extensions to DOS provided by Windows Just what is the relationship between the Windows kernel and the DPMI host Windows Extensions to INT 2Fh I would like to complete the coverage of the Windows extensions to INT 2Fh by discussing some more that can be very useful for DOS drivers and TSRs The others are covered at various points through the book namely Chapters 9 10 and 11 and can be located via the index I introduced INT 2Fh in Chapter 8 and have 4 provided a detailed summary of all INT 2Fh functions in Appendix D e INT 2F AX 1600h This function queries the version number of Enhanced mode Windows It returns AL and if the value is less than 3 or f greater than 127 then Enhanced mode isnt running Otherwise AL 3 and AH OAh for version 3 10 INT 2F AX 1680h Function 1680h yields the current VM s time slice You
61. LEA sp 83 move stack to free region TEXTEQU Something along these lines will give you access to the labels EQU within the callback Note that I used TEXTEQU because EQU cannot be used for text aliasing with ML a major divergence from earlier MASMs and from TASM Notice that the text to be aliased must be inside lt gt Anyway this is academic Other Incompatibilities PROC syntax So what else needs changing differences There is a slight difference in the syntax of the high level PROC directive If you look back to the declaration for WINMAIN you will see that it started like this WINMAIN PROC pascaL NEAR hinstance WORD With MASM6 it has to be rearranged like this WINMAIN PROC NEAR PASCAL hinstance WORD tt With TASMS Borland has allowed MASM high level PROC syntax STRUC I also came across an interesting problem with fields of a structure assembler Incidentally MASM6 allows nested structures which previous differences versions didnt Nesting is vital for OOP though MASM6 is still nothing like OOP aware The problem is that the program of this chapter has a couple of lines like this where clslpszmenuname is a 32 bit field of structure instance sl mov WORD PTR s1 clslpszmenuname ax mov WORD PTR sl clslpszmenuname 2 ds I loaded each half of the field with separate instructions MASM objects to a field being accessed in halves so I had to resort to MASM6 s solution lea di s1
62. Later chapters will expand this to 32 bit programming Real mode 16 bit programming can be considered an essential step up the ladder of understanding climbing through 16 bit Protected mode toward 32 bit Protected mode programming Chapter 4 puts this knowledge to use in a first 16 bit Windows application Discussion relates to the Microsoft and Borland assemblers though of course there are other compatibles 37 38 Windows Assembly Language amp Systems Programming Initialisation of the stack Purpose of the stack Cemporary storage saw GAEL RET w Interrupt mechanism Stack Instructions The computer maintains a stack somewhere in memory DOS will set the Stack Segment register SS when your program is loaded and the Stack Pointer SP will be initialised to FFFEh or some value that means the stack is empty The stack is used by the computer and by your program For example whenever an interrupt occurs the CPU pushes the IP CS and FLAGS onto the stack so that when the interrupt routine is finished terminated by an IRET instruction the CPU will pop these values back into the respective registers and continue from where it left off Thus the stack is used to hold register values to enable the CPU to return from an interrupt and also from a procedure CALL However you can make use of the stack in your program by means of the PUSH instruction which pushes a 16 bit value onto the stack and POP which pops the
63. Locations greater than bp contain the return address and passed parameters while addresses below bp 46 is the new working area for the stack WORD PTR override is introduced on page 63 High level Now we have another high level feature the high level CALL CALL lea call Or jne REGISTERCLASS only requires one parameter the FAR address of the sl data structure Refer back to how it was done before after everything was loaded into the structure in the stack segment ss bp 46 was passed as the FAR address required by REGISTERCLASS See page 99 onwards Below we do the same thing but use the name of the structure instead ax sl REGISTERCLASS PASCAL SS ax ax ax createwin jmp gquitwinmain 116 Windows Assembly Language amp Systems Programming createwin The time has come to create the window on screen The high level CALL has various qualifiers and can take multiple parameters Note that if the parameters have no defined size they default to WORD Notice the qualifier PASCAL call CREATEWINDOW PASCAL ds OFFSET szwinasminame ds OFFSET SeWAME OSH Ot pon ae 4400 O 0 0 hinstance 0 0 mov hWnd ax call SHOWWINDOW PASCAL ax nCmdShow call UPDATEWINDOW PASCAL hWnd jmp SHORT messageloop go to main message loop PASCAL C BASIC FORTRAN STDCALL PROLOG qualifiers You may have noticed that I have not used the FAR PTR override for the call instructions the assem
64. Microsofts own debugger can t even recognize what mode it is in The situation was I was writing code in a 32 bit segment 1 e with the Seg 16 _32 field in the descriptor set as introduced in the previous Figure In this situation the default size is 32 bits 0907 0200 0907 0201 32 bit Real mode Reference book 32 Bit Ring 0 291 Therefore all instructions will reference 32 bit registers operand size and address size without requiring an instruction prefix Thus 58 POP EAX 6658 POP Ax The situation is now reversed the 58h means ror EAX but if we write an instruction that only accesses a 16 bit register it will have the prefix appended It doesn t say much for Microsoft but Codeview version 4 01 despite being fully operational in 32 bit mode able to display the 32 bit registers and able to trace did not unassemble correctly At the time of writing 4 01 is my latest version it came with MASM version 6 1 and I m sure that by the time you read this book the bug will have disappeared So what of Real mode and virtual 86 mode In both of these modes the default is 16 bits but you may be very surprised to learn that in both modes you can use the 32 bit registers Of course the prefix or prefixes will be in front of every 32 bit instruction This may come as a complete surprise but use of 32 bit registers allows you to have segments greater than 64K up to 4 3G and thus break th
65. Notification Interrupt 2Fh Function 1606h and returns to MS DOS If the device driver or TSR can run in the Windows environment it should do the following 1 Call the next device driver or TSR in the Interrupt 2Fh chain to allow all device drivers and TSRs in the chain an opportunity to respond to this function 2 Upon return from the interrupt chain carry out the following actions a Free any extended memory The device driver or TSR takes this action only if it has previously allocated extended memory using the Extended Memory Soecitication XMS interface b Switch the processor to real mode or set the DS SI register pair to the address of an Enable Disable Virtual 8086 Mode callback function The device driver or TSR takes this action only if it has previously switched the processor to virtual 8086 mode If standard mode Windows is starting the device driver or TSR must switch the processor to real mode The callback function is permitted for 386 Enhanced mode Windows only c Initialise a Win386_Startup_ Info Struc structure and copy the address of the structure to the ES BX register pair The device driver or TSR carries out this action only if 386 Enhanced mode Windows is starting 3 Return using the iret instruction but without changing the CX register For more information about these procedures see the following comments The device driver or TSR must preserve all registers and restore the original va
66. PTR bp 201 long pointer far addr of push ss message we use the stack push ax region for convenience sub ax ax push ax null push ax null push ax null call GETMESSAGE Or ax ax only exit if returns AX 0 jne mainloop GetMessage returns FALSE AX 0 if a quit message so here we are guiting mov ax WORD PTR bp 161 return wParam to Windows quitwinmain mov sp bp POP hp r estore SP TO poine to Lhe return address ret 10 Causes RET to add 10 to SP after popping 102 Windows Assembly Language amp Systems Programming ret address effectively dumping all params as for PASCAL convention WINMAIN ENDP Figure 4 2 Stack at entry to GetMessage The above section of code starting at messageloop and l looping back to mainloop is the hWnd message loop Notice that the value wParam BP 20 was pushed onto the stack z This an offset address ae in the stack segment Pr where GETMESSAGE will place the message upon return The stack Segment is a old BP convenient temporary storage place ret addr etc Callback Function Thus ends WINMAIN For the callback function refer to the listing on page 79 The parameters are passed on to the stack in the order of left to right with a FAR return address on top If this program looks similar to the example in my last book it s not surprising since both were originally created from a C ske
67. Protected mode to Real mode Virtual IVTs CPU Architecture 35 There is a fascinating outcome of this From within a Windows application you can have an INT instruction let s say that you want to call the BIOS INT 10h service which controls the video adaptor INT 10h is not a service that Microsoft would want you to call from your application since all control of the video should be done by the Windows functions but you can do it A warning here some services will crash if called while in Protected mode and others will behave strangely Microsoft has in some cases provided alternative BIOS and DOS services written especially to run in Protected mode and when your program executes say INT 21h AH 35h the CPU will look up that entry in the IDT not the IVT and get the address Thus it is very easy for Microsoft to substitute its own services into the IDT In many cases probably most Microsoft services have not been substituted and execution goes to the original BIOS or DOS service Although the Real mode services may in some cases manipulate addresses in the form segment offset which will cause the code to crash if the CPU is running in Protected mode Windows gets around the problem by switching the CPU into Real mode or into virtual 86 mode then calling the service For such cases the entry in the IDT points to a special handler which apart from changing the CPU to Real mode must also convert any point
68. Repeat None REPE REPZ Repeat equal zero None REPNE REPNZ Repeat not equal not zero None RET immed far with pop RET far no pop RET immed near with pop RET near no pop Return None SAHF Store AH into flags SF ZF AF PF CF SAL SHL SAR SHR mem 1 SAL SHL SAR SHR reg 1 Shft arith tic left left shift arith right right OF 0 SF ZF PF CF SAL SHL SAR SHR mem CL SAL SHL SAR SHR mem cnt Shft arith tic left left shift arith right right SF SHR 0 ZF PF CF SAL SHL SAR SHR reg CL Shft arith tic left left shift arith right right SF ZF PF CF SAL SHL SAR SHR reg cnt Shft arith tic left left shift arith right right SF SHR 0 ZF PF CF 374 Windows Assembly Language amp Systems Programming Format Instruction Description Flags affected 86 286 386 SBB accum imm SBB mem imm SBB mem reg SBB reg imm SBB reg mem SBB reg reg Subtract with borrow OF SF ZF AF PF CEF SCAS repeat deststr SCAS deststr Scan byte word OF SF ZF AF PF CF SETxxx Conditional byte set None SGDT Store global descriptor table None SIDT Store Int descriptor table None SLDT Store local descriptor table None SMSW Store machine status word None STC STD STI Set CF DF IF CF 1 DF 1 IF 1 STOS repeat deststr STOS deststr Store byte word None STR Store task register None SUB accum imm SUB
69. SCROLL VK_OEM 1 VK_OEM_PLUS VK_OEM_COMMA VK_OEM_ MINUS VK_OEM_ PERIOD VK_OEM 2 VK_OEM 3 VK_OEM 4 to VK_OEM_8 VK_OEM_102 Keyboard Tables 381 SCROLL LOCK key Wnassigned Keyboard specific Plus key Comma key Minus key Period key Keyboard specific Keyboard specific Unassigned OEM specific nassigned 382 Windows Assembly Language amp Systems Programming Extended ANSI A gt H R f P Z Ao ee a n o amp mo E gt 1 Codes are in decimal Example 162 sp space per period _ Keyboard Tables 383 IBM ASCII 140 a 6 6 150 f 160 sp fi N a Q r 170 E y Z i i II I E l 180 4 4 fd Go 9 Fd a 4 o d a L L 2 FE 4 k H 200 I Ir 1 T j i l T 21 Tr bbp rn J r 220 m i I m a R T nm E a 230 u t d Q 6 co D H 240 gt lt r J 250 J n 2 E g 1 Codes are in decimal Example 162 6 sp space per period 384 Windows Assembly Language amp Systems Programming Windows documentation refers to IBM ASCII as the OEM or Terminal font It is the standard 8 bit ASCII character set supported by DOS Some other fonts also support this character set such as LotusLineDraw DPMI Services This material is extracted with permission from the DOS Protected Mode Interface DPMI Specification Version 1 0 by the DPMI Committee hosted by Intel Corporation Detailed information is provided here for version 0 9 be
70. SS None LTR Load task register None MOV 16 reg segreg MOV accum mem MOV mem accum MOV mem imm MOV mem reg MOV mem segreg MOV reg imm MOV reg mem MOV reg reg MOV segreg 16 mem MOV segreg 16 reg Move None MOVS repeat deststr sourcstr MOVS deststr sourcestr Move string None mane MOVSX Move with sign extension None MOVZX love with zero extension None zZ MUL 16 mem MUL 16 reg MUL 8 mem MUL 8 reg Multiply OF CF NEG mem NEG reg Change sign OF SF ZF AF PF CE NOP No operation None NOT mem NOT reg Invert None OR accum imm OR mem imm OR mem reg OR reg imm OR reg mem OR reg reg Logical OR OF 0 SF ZF PF CF 0 OUT 8 immed accum OUT DX accum Output to port DX port None OUTS rep DX sourcestr Output string None OUTS DX sourcestr Output string None POP mem POP reg Restore from stack None POPA Restore general reg s fromstack All PUSH imm Save to stack None PUSH mem PUSH reg Save to stack None PUSHA Save all to stack None PUSHF Save flags to stack None RCL RCR ROL ROR mem 1 RCL RCR ROL ROR reg 1 rotate thru CF left CF right rot left right OF CF Instruction Summary 373 RCL RCR ROL ROR mem CL RCL RCR ROL ROR reg CL rotate thru CF left CF right rots left right CF RCL RCR ROL ROR mem cnt RCL RCR ROL ROR reg cnt rotate thru CF left CF right rot left right CF REP
71. Systems Journal May 1993 pages 29 37 Early in 1993 I was trying to figure out how to do this but Matt had an advantage over me inside information His technique makes use of two undocumented features which he thinks are likely to stay in future versions of Windows Basically Matt was writing from the point of view of a Windows 3 1 application which would normally be running in 16 bit mode Now let me clarify one point this entire chapter assumes Enhanced mode Windows only using a 386 or above Windows 3 1 can run in Standard mode but the 286 CPU has gone the same way as the 8088 This confuses everybody but Windows running in Enhanced mode can be running in 16 bit or 32 bit mode Windows NT runs 32 Bit Ring 0 289 normal native applications in 32 bit mode and Windows 95 encourages this In Matt s article his application was running in 16 bit mode and when he switched up or down to ring 0 he stayed in 16 bit mode Obviously this is a point of great potential confusion so this chapter commences by explaining the difference between 16 bit and 32 bit programming Chapter 1 shows the structure of a descriptor however it is now time to examine it in more detail Figure 12 1 shows the full detail Figure 12 1 Detail of the code descriptor CODE DESCRIPTOR OFFSET 7 0 Low part of the size of the segment bits 0 15 va Linear starting address of the segment Limit 8 15 bits 0 23 B eA Accessed B
72. TSR must identify itself by responding to the notification and adding itself to a linked list of Windows aware TSRs A Windows aware TSR can also direct Windows to load a Windows based application or a DLL such as an installable driver to allow the TSR s services to continue running properly inside the Windows environment Each TSR must monitor Interrupt 2Fh and respond to the startup broadcast by attaching itself to a linked list A TSR that intercepts this broadcast must do the following Allocate space for a TSR_Info Struc structure 2 At the minimum fill in the TSR_PSP_Segment TSR_API_Ver_ID and TSR_ID_Block fields 3 Save the current content of the ES DI register pair in the TSR Next field 4 Set the ES DI register to point to its own TSR_Info Struc structure 5 Pass execution control to the next handler in the Interrupt 2Fh chain A TSR should never assume that the ES DI register pair is 0 0 because it may not be the first TSR on the Interrupt 2Fh chain A TSR must always chain to the next Interrupt 2Fh handler so that TSRs following it in the chain can add themselves to the Windows aware linked list The TSR_Info_Struc structure defined in the DDK include file INT2FAPI INC is a Microsoft Macro assembler structure see end of this Appendix Interrupt 2Fh Function 1680h Release Current VM Time Slice Directs Windows to susvend the time slice of the current VM and start a new time slice for another VM M
73. TSR or use the vector as a pointer to global data Any data passed to the TSR s own data area will also be available to a Windows application that calls that same TSR End of story This method works quite happily for Enhanced or Standard modes but is awkward in that the TSR must be loaded before Windows Also it takes up valuable space in that first 1M This simple technique for sharing data works across all VMs because the same TSR is present in all I develop this point as I go along This idea of using a global DOS TSR is not the only approach but is quite powerful and it is the basis for discussion in this chapter Reference The problem of different VTs in each virtual machine is discussed source by Thomas Olsen in Making Windows amp DOS Programs Talk Windows DOS Developer s Journal May 1992 p 21 276 Windows Assembly Language amp Systems Programming Mapping the IVT and TSR across VMs He does not see any way around this problem except by loading the DOS TSR before loading Windows Actually if you only want the DOS TSR to load into the system VM and not subsequent VMs you can force this by naming it in a file called WINSTART BAT which Windows looks at to see what has to be done before loading itself but after creating the system VM Simply put the name of the TSR in it as per a normal batch file When I say there s nothing to it Fm being a bit flippant A DOS TSR loaded before Windows
74. Tells the display driver to restore the video hardware state saved by 400 1 h e AX 4003h Tells Windows Virtual Display Driver VDD that execution is currently in a critical section This function appears to make the VDD pause until 4004h releases it e AX 4004h Tells VDD that critical section is finished e AX 4005h Similar to function 400 1 h e AX 4006h Similar to function 4002h e AX 4007h A program tells the VDD that it has finished accessing the hardware registers This is the complement of 4000h I think it unlikely that you will need to call 4000h and 4007h unless you are designing your own display driver 4000h is designed for use by a display driver to communicate with the VDD prior to the VDD calling 4005h This sequence terminates when 206 Windows Assembly Language amp Systems Programming Real and virtual driver interaction the VDD calls 4006h to let the display driver restore its state and continue functioning After this the display driver calls 4007h to tell the VDD that it s all over Chapter 9 has an example of usage and Appendix D is an INT 2Fh reference Another group of INT 2Fh functions has to do with communication between DOS Real mode drivers and virtual mode drivers VxDs I have noted below that some of the functions have been used in example programs along with more detail on their usage Also Chapter 11 discusses these functions in more depth Note that only functions 1605h and 1
75. Test TR6 7 regs This code shows how to get the single byte memory contents in the ES segment at offset BX in the first case and EBX in the second Obviously the first instruction is limited to a 64K segment due to BX being 16 bits while the use of EBX extends the limit to 4 3G Memory management Multitasking problems Distinction between 286 and 386 Purpose of the LDT CPU Architecture 25 Real and Protected Modes It has already been stated that when in Real mode the 386 and 286 operate like the 86 with segment registers having actual segment paragraph addresses The limitation this imposes is that the maximum address range is 1M plus the extra 64K high memory area see page 17 Another limitation is that there is no built in support for memory management Windows allows more than one program task to run at once and this introduces some incredible constraints Also simplicity goes out the window Obviously the CPU must be able to divide its time between running the various programs each must sit in separate areas of memory and none must write to memory where another program is sitting They must be able to share keyboard input and not scribble all over the screen each task must only output to its own window Other resources and I O must be shared without a fight This is asking a lot but the Protected mode inherited from the 286 will do it while the Enhanced protected modes of the 386 will d
76. UE PE FDIVR dest source Divide real reversed IE DE ZE OE UE PE FDIVRP dest source Divide real reversed amp pop IE DE ZE OE UE PE FENI FNENI Enable interrupts None FFREE dest Free register None FIADD source Integer add IE DE OE PE FICOM source Integer compare IE DE FICOMP source Integer compare amp pop IE DE FIDIV source Integer divide IE DE ZE OE UE PE FIDIVR source Integer divide reversed IE DE ZE OE UE PE FILD source Integer load IE FIMUL source Integer multiply IE DE OE PE 376 Windows Assembly Language amp Systems Programming Format Instruction Description F lags affected 87 287 387 FINCSTP Increment stack pointer None FINIT FNINIT Initialise processor None FIST dest Integer store IE PE FISTP dest Integer store amp pop IE Pe FISUB source Integer subtract IE DE OE PE FISUBR source Integer subtract reversed IE DE OE PE FLD source Load real IE DE FLD1 Load 41 0 TE FLDCW source Load control word None FLDENV source Load environment None FLDL2E i Load log 2 e IE FLDL2T Load log 2 10 IE FLDLG2 Z Load loq 10 2 IE FLDLN2 Load log e 2 IE FLDPI Load pi IE FLDZ Load 0 0 IE FMUL dest source Multiply real IE DE ZE OE UE PE FMULP dest source Multiply real amp pop IE DE ZE OE UE PE FNOP No operation
77. WM_DESTROY call wmdestroy ELSEIF ax WM_ RBUTTONDOWN call alata ELSEIF WM SIZE call FERTA ELSEIF ax WM_CREATE call wmcreate ELSEIF ax WM_LBUTTONDOWN call wmlbuttondown ELSEIF ax WM_PAINT call wmpaint ELSEIF ax WM_ COMMAND call wmcommand ELSE call DefWindowProc hwnd wmsg wparam lparam ret ENDIF xor eax eax ret ASMWNDPROC ENDP t m u ew ew me ee eee o eee we a a e ew em ew e X ew ew X Kem X XXX 32 bit Ring 3 313 wmcommand PROC mov ax WORD PTR g_lparam IF ax 0 mov ax WORD PTR g_wparam IF ax IDM_QUIT call PostQuitMessage O ELSEIF ax IDM_ABOUT call MessageBox g_hwnd OFFSET szaboutstr OFFSET sztitlestr MB _OK ENDIF ENDIF ret wmcommand ENDP i wmpaint PROC call BeginPaint hwnd OFFSET s3 mov hDC eax call EndPaint hwnd OFFSET s3 Yer wmpaint ENDP wmcreate PROC ret wmcreate ENDP wmdestroy PROC call PostQuitMessage O ret wmdestroy ENDP wmlbuttondown PROC ret wmlbuttondown ENDP wmrbuttondown PROC call MessageBeep 0 ret wmrbuttondown ENDP wmsize PROC ret wmsize ENDP END start Elegant isn t it You can refertoearlier chapters for explanations of how each part works You might like to compare it with the 16 bit MASM6 program in Chapter 5 The differences are small Most importantly you do everything in 32 bits 314 Windows Assembly Language amp Systems Programming The differences between 76 and 32 bit coding
78. Window class data structure Continuing the program listing WINDOWdefinewndclass PROC PASCAL pwndclass now push di push si mov si now mov di pwndclass pointer to wndclassa see make getup the window class structure for REGISTERCLASSO mov ax si classstyle get specs from object and load mov dil clsStyle ax into wndclassa structure mov di WORD PTR clsLpfnWndProc OFFSET exportwndproc mov di WORD PTR clsLpfnWndProc 2 SEG exportwndproc mov di clsCbClsExtra 0 mov di clsCbWndExtra 2 mov ax mainl hInstance mov di clsHInstance ax cmp si sziconname 0 je noicon lea ax si sziconname call LOADICON PASCAL mainl hinstance ds ax jmp SHORT yesicon noicon call LOADICON PASCAL null O IDI_APPLICATION yesicon mov di clsHIcon ax cmp sil szcursorname O ie nocursor ea ax si szcursorname call LOADCURSOR PASCAL mainl hinstance ds ax jmp SHORT yescursor nocursor call LOADCURSOR PASCAL null O IDC_ARROW yescursor mov di clsHCursor ax mov ax si hbrbackground mov di clsHbrBackground ax lea ax si szclassname mov di WORD PTR clsLpszMenuname ax mov di WORD PTR clsLpszMenuName 2 ds mov di WORD PTR clsLpszClassName ax mov di WORD PTR clsLpszClassName 2 ds pop si pop di ret WINDOWdefinewndclass ENDP Program Design 7 The above routine simply copies data from the object into wndclassa Default What follows are the default routines funct
79. an ASCII table 00110100 represents ASCH character 4 An ASCII character is any single symbol such as a numeric digit letter punctuation symbol etc Each key on the keyboard represents one character The 4 key for example when pressed is stored inside the computer not as the binary value 00000100 but as the ASCII code 00110100 The bit string does not represent a character or a value but an instruction operation code Machine language instructions are stored in memory as op codes followed by zero or more operands depending upon the instruction the interpretation of this code is up to the CPU There are many more possibilities for example a value stored in memory could be an address This may at first seem confusing but you could store address pointers to data in memory So far in this section we have looked at the different interpretations of 00110100 but it is also important to know that there are different bases or radices in which the number can be represented We saw above that 00110100 is 52 in decimal That is 00110100 is the representation in binary with radix 2 and 52 is the representation in decimal with radix 10 Note that 52 is just a digit string like 00110100 and interpretation as a number is our choice Actually numbers can be represented in any base Most important for us apart from binary and decimal is the hexadecimal representation The next section will start to throw hex numbers at
80. an interesting consideration a classical problem with visual programming environments is that they tend to very rapidly run out of screen but LabView is the most compact and screen efficient of any VPL that I have encountered Just imagine being able to rapidly wire up a program without having to remember any text based syntax or even how to use pointers Disadvantages of LabView Ok ok the negative points The power comes at a price which is inefficiency of the generated code LabView programs are HUGE and they dont run at the speed of compiled C as National Instruments publicity would have you believe Maybe you can contrive such a situation but practical programs would be lucky to achieve half the speed of an equivalent C program However equivalent is a difficult issue because LabView applications have so much extra stuff built in Compared with one of LabView s main competitors HP VEE developed by Hewlett Packard the former is much faster and in my personal opinion far more sophisticated and mature Advanced Systems Programming 361 Figure 15 3 LabView icon front panel and diagram Valve Deadband Lag min Update P T Manipulated Variable Outpu Process Gain Process Load Process Deadtime Noise Update PV IT Plant Characteristics a Piocess Gar Process Loadh I Read 5 50 Manipulated Variable Output ao Process Variable Process Variable
81. any address can be replaced by a label so if you had defined address 567 as being represented by label VALI for example then this would do the same thing Both of these are called direct addressing Do note one point about syntax The last instruction could have square brackets around VAL 1 and it would be interpreted exactly the same by the assembler TASM or MASM Indirect addressing is somewhat more abstract It means that the contents of the operand are used as the address So the content of BX is the address from which the value is fetched into AX bx indexed addressing mode bx 5 af bx si 5 That just about covers it except that indirect addressing does have some options as shown in the last two instructions above The first one adds the contents of BX to 5 and the result is the address while the second example adds the contents of BX SI and 5 to form the address This modified form of indirect addressing is called indirect plus displacement if a constant is specified or indexed indirect if two registers are specifed Note that we often just label these various indirect modes under the title of indexed addressing 46 Windows Assembly Language amp Systems Programming Note also that there are restrictions on the combinations of registers allowed within the brackets you can have SI or DI but not both and you can have BX or BP but not both No other registers are allowed Segment Registers An
82. apart from REPAINTSCREEN listed above and apart from those inside the display and printer drivers They are ADVANCEDSETUPDIALOG BITBLT CHECKCURSOR COLORINFO CONTROL DEVICEBITMAP DEVICEBITMAPBITS DEVICEMODE DISABLE ENABLE ENUMDFONTS ENUMOBJ EXTDEVICEMODE EXTTEXTOUT FASTBORDER GETCHARWIDTH GETDRIVERRESOURCEID GETPALETTE GETPALTRANS INQUIRE MOVECURSOR OUTPUT PIXEL QUERYDEVICENAMES REALIZEOBJECT SAVESCREENBITMAP SCANLR SELECTBITMAP SETATTRIBUTE SETCURSOR SETDIBITSTODEVICE SETPALETTE SETPALTRANS STRETCHBLT STRETCHDIBITS UPDATECOLORS USERREPAINTDISABLE WEP There is also a group of low level communication functions BUILDCOMMDCB CLEARCOMMBREAK CLOSECOMM ESCAPECOMMFUNCTION FLUSHCOMM GETCOMMERROR GETCOMMEVENTMASK GETCOMMSTATE TOOLHELP low level functions BIOS DOS Windows Services 213 OPENCOMM READCOMM SETCOMMBBEAK SETCOMMEVENTMASK SETCOMMSTATE TRANSMITCOMMCHAR WBITECOMM In addition there is a group of sound functions utility macros and functions file I O functions and debugging functions For lists of these groups refer to Microsoft SDK Reference Volume I A special group of low level functions have been provided with Windows 3 1 and documented in the SDK 3 1 They are supplied in TOOLHELP DLL and are backwards compatible with Windows 3 0 but you must bundle TOOLHELP DLL with your program The equivalent Win95 functions follow this list The TOOLHELP functions are e C
83. are provided by Windows They are designed especially for the difficulty of using DMA controllers with a CPU running in Protected mode Windows Functions There are some Windows functions that perform in a similar manner to DPMI services so there is overlap What I have done in this section is not give exhaustive definitions of the functions as that would require a complete book on its own You need a lot of reference material for Windows development and where appropriate I have given the reference There are two broad groups of functions those available in USER KERNEL or GDIDLLs and those available within device drivers and other DLLs In the latter case you will find functions of the same name For example enable and disable exist in all drivers Obviously your program must be able to select which one it is to call and that I have shown in the next chapter The Windows functions are all in files known as Dynamic Link Libraries DLLs and are loaded at run time What follows is a collection of Windows functions that you may find useful for low level work The list immediately below all belong in either USER KERNEL or GDI DLLs Note that although many of the memory management functions could be considered low level I have only included those directly concerned with descriptors and selectors with one exception GLOBALPAGELOCK Functions are in Windows 3 0 and 3 1 unless stated otherwise even if documented in one
84. are loaded into RAM during power on Actually you may recall from Chapter 1 that the hidden system tile MSDOS SYS has these DOS routines except in the case of Windows 95 So what is the major difference between the services provided by BIOS and those provided by DOS The answer is that the BIOS services are low level that is they are for more basic access to and control of the hardware of the PC The DOS routines provide mostly higher level access to and control of the hardware and resources of the the PC Note also that some of the DOS routines are not actually for accessing hardware rather they are operating system management functions PCI bridge Configuration memory PC Hardware 9 Peripheral Connect Interface PCI Figure 7 7 shows a typical configuration though do note that there can be variations on this For example RAM memory could be interfaced to the PCI bus rather than directly onto the CPU bus or both Figure 7 7 PC amp CPU ISA bridges The PCI bridge is a chip and although it is not obvious from the figure there are different kinds of chips for different bridges such as between CPU PCI and PCI ISA Also the PCI plug in cards themselves will have a PCI chip One great advantage of having a special bridge chip between buses is that they allow address translation so that a memory or I O address on the CPU bus will be a different address on the PCI bus In fact the bridge chip is high
85. as shown Also your source program should have WINVER 0x0300 before the WINDOWS INC is included if uSing a WINDOWS INC derived from WINDOWS H supplied with SDK 3 1 my WINDOWS INC on the Companion Disk is derived from SDK 3 0 whiicim avoids certain problems When you type this in there is no need to put in all the comments but be careful about unnecessary blank lines and leave a blank line where I have put one There are certain syntax requirements that can be messed up otherwise Note that its on the Companion Disk SSKELETN2 to save you all that trouble The MAK tile shows where it expects all of the files to be located but you can make changes as necessary You could even put everything in the one directory as I suggested as a quick and dirty option for Microsoft if the SDK isnt installed see page 86 Ditto you could do this with the Borland tiles but if you have the complete distribution disks then why not install properly in which case the files will load into the above directories by default MASM6 versus TASM MASM version 6 00 is a curious beastie It was in some respects a disappointment especially as I acquired it soon after obtaining TASM v3 0 and had been spoilt by the wonderful new features Borland had incorporated into their assembler However while MASM may not be OOP aware it does make ground in other ways Hmmm MASM v6 0 isnt even 126 Windows Assembly Language amp Systems Pr
86. assembly language MASM version 6 is a bit different see page 125 as is TASM version 5 see Chapter 13 EXTRN UPDATEWINDOW FAR EXTRN BEGINPAINT FAR ENDPAINT FAR EXTRN DEFWINDOWPROC FAR EXTRN POSTQUITMESSAGE FAR EXTRN REGISTERCLASS FAR EXTRN GETSTOCKOBJECT FAR EXTRN CREATEWINDOW FAR EXTRN SHOWWINDOW FAR EXTRN GETMESSAGE FAR EXTRN LOADCURSOR FAR EXTRN TRANSLATEMESSAGE FAR EXTRN DISPATCHMESSAGE FAR EXTRN LOADICON FAR EXTRN TEXTOUT FAR EXTRN MESSAGEBOX FAR EXTRN SELECTOBJECT FAR Data segment no major change from before T DATA szwintitle DB HULLO DEMO PROGRAM 0 szwinasmlname DB WINASM1 0 hOemFont DW 0 handle to OEM font sout DB Hullo World szabout DB Assembly Language Windows Demo 0 sztitle DB Karda Prints 0 CODE PUBLIC WINMAIN WINMAINPROC PASCAL NEAR hInstance WORD hPreviInstance WORD lpCmdLine DWORD nCmdShow WORD High Level Assembly 113 High level Now for the first major enhancement If you refer back to page 98 PROC you will see this same section of code and a picture of the stack The parameters passed on the stack have to be accessed by direct addressing of the stack segment cmp worp PTR bp 10 0 for example to get at hPrevInstance However by declaring all passed parameters as above they can be accessed within the procedure by name The example would become cmp hPrevinstance 0 simple hey The assembler equates hPrevinstance to bp 10 so i
87. ax ds shl ax 4 convert para to offset jc over64k add dx ax get FLAT linear 32 bit address xor ax ax A mov ds ax gt ds dx bb2 mov ax 2560h hook int 60h int 21h push cs pop i restore ds ds i e real address is segment 0 offset dx works only if in 1st 64K WINAPP can check the hi 2 bytes of int 60h ivt to confirm that they are zero and that no other program has overwritten no be careful take care of over 64K over64k add dx ax as above not likely to produce carry mov ax 1 jthis is the carry mov ds ax jmp bb2 bb3 terminate leave resident lea dx dumpme point past all code in this module shr dx 4 compute paragraphs to keep add dx psp_size mov ax 3100h terminate and stay resident int 21h abortload call longbeep mov ax 4cooh don t make resident int 21h END start DOS Win Transitions 337 Universal The hooking of IVT vectors in the above code is very ordinary but global you will find the creation of the global data and FLAT linear pointer address to be interesting A slightly negative point about this global data is that it is in the first 1M i e conventional memory The FLAT address is simple to calculate because it is just an addition DS 16 OFFSET globaldata It is actually only 16 or 17 bits in size as this TSR is close to the start of linear memory so the higher bits are zero I stuck this pointer into the IVT at entry 60h whic
88. can be a FAR or NEAR jump What this means is that if the jump is NEAR the jump is only within the current code segment that is only the IP is altered as per Figure 2 2 A FAR jump or call however can be to anywhere in the entire 1M address range as both CS and IP are altered In Figure 2 2 the procedure ROUTINEX is shown as being in the same code segment as the CALL instruction but it could be somewhere entirely different Obviously if ROUTINEX is in a different code segment then both CS and IP in the CPU would have to be changed to the new values Note that it also logically follows that the original values of CS IP immediately after the CALL would both have to be saved on the stack and RET would have to restore both of them at the end of the procedure Note that with what is called 32 bit programming the distinction between NEAR and FAR just about disappears One thing that you will notice from Figure 2 2 is that I used a code label ROUTINEX to name the start of the procedure This is basically what you expect to be able to do in any high level language and you can also do this in assembly language A code label marks or identities that point in the code hence a CALL was able to be made to that place Code labels With a professional assembler such as the Borland TASM or with MASM Microsoft MASM these labels are a normal part of writing a TASM program but DEBUG is a different story DEBUG DEBUG CANNOT HAVE LABE
89. can communicate with Windows and Windows programs Now the picture is to be tilled in a little more One thing that you may have noticed with some hardware products such as network cards is that they come withtwo sets of device drivers one for DOS and one for Windows Actually in most cases the DOS driver will work under Windows but less efficiently than one written specifically for Windows The reason for this is that Windows has to pass control down to V86 mode to access the DOS driver which means time overhead To be more correct there are three different types of device drivers because the old Standard mode sorry Im mentioning it again cannot use virtual device drivers However I wont worry about Standard mode drivers Therefore a logical question arises if you install a DOS device driver via the CONFIG SYS tile that will be tine for DOS but if you then load Windows which will load device drivers specified in the SYSTEM INI file how do you avoid the two drivers clashing Now apply this line of thinking to TSRs You have a DOS TSR which as described earlier you can make Windows aware However the same problem exists a TSR is written for Real mode Therefore maybe you would like an automatic transition to take place from the TSR to a Windows application For both the device driver case and the TSR case you want a smooth and transparent mechanism for transferring to an equivalent Windows program Microsoft has
90. can produce This is PREC true to the present day no matter how optimised compilers have become For example Quantasm Corp sell a floating point emulation library to replace the standard ones Its written in assembly language and is typically 4 to 10 of the size and 5 to 10 times as fast as most C floating point libraries Apart from size and speed there are other major issues The contention that assembly language is harder to write in than a high level language is I hesitate to say nonsense Il just say maybe in some cases I can throw assembly code together as fast as with C My assembler does not perform the kind of checking that a compiler will but Microsoft MASM version 6 x and Borland TASM version 5 have significant C like checking Portability Transportability is a major consideration If code is to be transported to other platforms that is other CPUs running Windows shouldnt I avoid assembly language Yes and no For a Start the issue only applies to Windows NT If you examine any high level program such as a C program you will find that it is riddled with hardware dependency Hardware dependent statements are written in a high level language throughout typical programs Whenever I see low level functionality being coded in a high level language I find it to be cumbersome inefficient and in many cases unreadable Why force a square peg into a round hole Why not just bite the bullet and code those portion
91. catered to this need Automatic Loading of Windows Programs Drivers The example code for this section is on the Companion Disk in directory TSR2WIN It contains a TSR called TSR2WIN ASM that assembles and links to TSR2WIN EXE What this TSR does is detect when Windows is loading automatically loads a virtual device driver VxD and also loads a Windows application Note that you could just as easily have loaded the virtual device driver from a DOS device driver the principle is the same Global data The invisible xD TSRZWIN TSR The TSR is inside the xD DOS Win Transitions 331 Another bonus of this TSR is that it establishes a global data area and provides a FLAT 32 bit linear address for it that the Windows application and the device driver can access An interesting aspect to how this TSR works is that neither the VxD nor the WinApp need to be specified in a INI file It is usual to put a DEVICE line inside SYSTEM INI to cause a VxD to load but the TSR will load the VxD without such a line Furthermore although Microsoft recommends that all VxDs should be in WINDOWS SYSTEM directory the documentation does not say that they have to be Thus you can put your VxD anywhere TSR Installation Essential portions of TSR2WIN are reproduced here and this is sufficient for you without having the original source files from the Companion Disk if you are familiar with basic TSRs Re
92. circumstances you cannot use the MOV with OFFSET override and must instead use LEA Load Effective Address LEA is clarified below but first why can t OFFSET always be used The answer is that you would only use OFFSET if place2 is defined in the data or code segment and not if defined as LOCAL see page 62 The fundamental reason is a built in limitation to the addressing modes of the MOV instruction Automatic data or any data of a temporary nature created and destroyed during run time as opposed to permanent data assembled into the data or code segment is usually addressed using indexed mode or register relative mode Look at this example PROC ptr4 DWORD local data created on stack lea DI ptr4 ret routine2 LFA compared with OFFSET ENDP The assembler will equate ptr4 to BP v amp e whereas if ptr4 had been defined in the data segment by something like ptr4 pw o0 the assembler would equate ptr4 to an offset relative to DS BP is something that varies at run time so in the first case ptr4 can only be equated in this way The problem arises if you compare the above LEA instruction with something like mov di OFFSET ptr4 the latter will not work it will load the content of ptr4 rather than its offset This MOV instruction is translated by the assembler to mov di bp value and this indexed mode cannot be immediate It must be non immediate So the golden rule is Only use MOV re
93. depends on the specific action requested Comments This function typically is used by a virtual device to communicate with the driver or TSR that explicitly loaded the virtual device It is up to the virtual device to supply a correct device identifier and any other parameters that specify what action to take It is up to the driver or TSR to monitor Interrupt 2Fh and respond to the function appropriately iA virtual device can call this function at any time either in Real mode or after 386 Enhanced mode Windows has started tnterrupt 2Fh Function 1608h Windows Initialization Complete Notification INotifies MS DOS device drivers and TSRs that 386 Enhanced mode Windows has completed iits initialization Windows calls this function after it has installed and initialized all virtual 406 Windows Assembly Language amp Systems Programming FORMAT Heading Description Call with Returns Comments _ devices allowing MS DOS device drivers and TSRs that monitor Interrupt 2Fh the opportunity to identify instance data and perform other functions that are restricted to 386 Enhanced mode Windows initialization Call with AX 1608h Return value This function has no return value Comments When Windows calls this function all virtual device initialization is complete so a device driver or TSR can call virtual device entry points Windows does not necessarily call this function immediately after callin
94. device not available respectively Again these are exceptions There is a very serious problem with this arrangement With the 286 and 386 Intel uses the first 16 entries of the interrupt table and now we must refer to the IDT as exceptions when the CPU is operating in Protected mode However the hardware interrupts IRQO through 7 are mapped into INT 8 to Fh Quandary how is this conflict resolved Windows and OS 2 map IRQO through Fh elsewhere in the IDT at INT 50h to 5Fh Obviously these entries would point to the same routines as before but even so there is room here for trouble You might deduce from this that if you wanted to hook the original INT 8 you should instead hook INT 50h This is valid but only to a certain extent Windows can be in Protected or V86 mode at the time of interrupt and in the latter case we have to go back to the VT in the V86 virtual machine currently active Therefore we may actually have to hook two or more vectors Headache Windows Standard Mode Hardware Interrupts Somewhere earlier in the book I promised not to mention Standard mode again as it s history almost Maybe in some third world I don t want to be misleading here In Windows Standard mode when a DOS program is running the CPU will be in the one and only Real mode and interrupts vector via the one and only IVT However in Enhanced mode with a DOS VM active it is still a Protected mode
95. ebx ebx no old owner jz short process io no just process VMMCall Enable_Local_Trapping old owner now locked out process io popad secondly handle I O Dispatch_ Byte_IO Fall Through lt SHORT VDEMOD_Out gt in al dadx do real in ret VDEMOD _Out out dx al do real out ret dontgrocess popad r restore regs mov al OEh indicate error to sample apps IFDEF DEBUG Trace Out VDEMOD I O inhibited for VM EBX Advanced Systems Programming 357 ENDIF ret EndProc My _VDEMOD_Hook BeginProc My VDEMOD lpt Hook we come here if the ea as status ports are trapped set bit 3 7 clear bit 4 pushad popad Dispatch Byte IO Fall Through lt SHORT VDEMOD lpt Out gt in al dadx do rear in mov al 10101000b this should stuff up printing ret busy out 0f paper offline error VDEMOD_lpt_Out out dx al do real out ret EndProc My_VDEMOD_lpt_Hook BeginProc ctri VDEMOD IOO Ot ee ey et we come here if the printer control ports are trapped pushad popad Dispatch Byte 10 Fall Through lt SHORT ctrl lpt Out gt in al dx do real in mov al 0 Fer ctrl lpt_Out g out dx al do real out mov al 00001000b bit 3 1 printer not selected out dx al ret ENG EOE ctrl_VDEMOD_lpt_Hook xb _CODE_ENDS END Totake this further you need a good book with all the details on the VMM services Install_IO_Handler for example hooks a port and redirects to a callback routine The routine i
96. fact that one of the fundamental concepts behind the LDT is that there should be one per task Windows maintains just one for the entire VM This is why obtaining a selector when installing a TSR Real ModeAccess 275 will work within the TSR s run time code no matter which WinApp is running at the time of the interrupt However an interrupt when in another VM will access a different LDT and IVT This idea of one LDT per VM is in keeping with DPMI version 0 9 Version O has an LDT per client task Windows is one client only Accessing The conclusion here is that accessing Real mode code via the Real mode IVT from a Protected mode WinApp accesses it in the system code in all VM If you want to get at code or data of a DOSApp or TSR in VMs another VM you have to look into mechanisms for going between VMs or if you load a DOS TSR before Windows it will be automatically in all VMs and thus its code and data will be global Even its hooking of the IVT will be in every IVT Thus the DOS TSR is one convenient mechanism for communication between Protected and Real modes across all VMs and is developed further in this chapter Also a method for switching VMs is developed Accessing Protected Mode from Real Mode Global data Actually using the global DOS TSR method by passing data via a DOS between Real and Protected modes is very easy JSR All that the DOS application has to do is execute a software interrupt to invoke the
97. fascinating to watch the game Microsoft and Borland are playing with each other One tries to leapfrog the other and Microsofts version 6 0 was released in response to Borland version 2 5 MASM version 6 0 has some very nice features and the releases of 6 10 and 6 11 added enhancements to further streamline coding for Windows Ive put some special notes on compatibility issues for v6 0 at the end of this chapter see page 125 and to be completely fair to both vendors and to those readers who have MASM v6 x Ive placed a complete listing of a MASM skeleton program at the end of this chapter You will also find the MASM skeleton program on the Companion Disk in directories ASMDEMO1 and ASMDEMO2 The first is a skeleton program that has the startup code inside the program as is done in the skeleton program of the previous chapter In the second directory is the same program but it has the startup code as a separate linkable module It is the latter case that is listed at the end of this chapter You will find the TASM skeleton program on the Companion Disk in directory SKELETN2 This is the same program listed immediately below Note that it has a separate linked startup module COWS OBJ You may have already noticed that there is nothing apparently logical about the naming of directories or files on the Compnaion Disk The justification is historical I have kept the same names as used in the first edition A skeleton written for T
98. find that the 8088 derivatives are selling very strongly today possibly in larger quantities than the Pentium I m very much into the design of the lower end of embedded systems using the more humble 8 and 16 bit processors as covered in my book Flow Design for Embedded Systems R amp D Books Miller Freeman USA 1997 For more information see http www rdbooks com Figure 1 5 Three parts of a computer bus Address bus 8086 CPU 20 bits CPU and 286 CPU 24 bits 386 CPU 32 bits support Data bus 8088 CPU 8 bits 8086 amp 286 CPU 16 bits 386 32 bits chips Control bus Three parts of The 8088 is the Central Processing Unit CPU of the PC It a computer bus executes instructions contained in RAM or ROM The CPU and a few support chips produce various signals known as the bus which can be broken down as shown in Figure 1 5 The lines are physical wires going to and from the CPU and support chips The bus goes to all the memory and I O input output chips in the computer and is the means by which everything communicates 14 Windows Assembly Language amp Systems Programming Extended conventional high Memory map of the PC Protected mode History of Intel CPUs Conventional and Extended Memory Extended memory is that above the 1 megabyte M address limit while conventional memory is below 1M Expanded memory is bank switched memory that can be mapped into the conventional me
99. havent actually defined such a function object active is a data member of window1 and I have accessed it in the stack Notice also how I can access functions of other objects and a box1 is some other object belonging to a different class say different BOX The choice here is arbitrary It has an arbitrary function object called draw Compile and Assemble Steps If we use Borlands BCC compiler the command line to compile to assembly is as follows BCC c S filename CPP Where c suppresses linking and generates ASM output Note that case is important with the switches Mangled The filename ASM file that you get will not have any high level names assembly language features in it so you have to look through it and extract the useful information Then you can put together your own assembly module It will look something like this 152 Windows Assembly Language amp Systems Programming MODEL SMALL must match C module PUBLIC WINDOW TEXTOUTSqii EXTRN WINDOW dosomething qv NEAR EXTRN BOX draw qii EXTRN _boxl1 DATA x DWO local data CODE WINDOW TEXTOUT qii PROC C now vall val2 show to get at the passed parameters mov si now actually at bp 4 Addr of windowl mov ax vall actually at bp 6 mov bx val2 actually at bp 8 to access another function another object box1l draw 1 2 lea ax boxl call BOX draw qii C ax 1 2 early binding to access a function current objec
100. i e the result is 1 or in binary 00000001 Obviously AL is greater than 127 but that is only if you treat the numbers as unsigned As a 2 s complement number 128 is actually 128 0 lt gt 127 128 lt gt 255 or 00 7F 80 FF in Hex O0 lt gt 127 128 lt gt 1 or 00 7F 80 FF in Hex So from a 2 s complement point of view AL is less than the operand 127 That is why there are different conditional jump instructions for signed and unsigned numbers Following the CMP AL 127 we could have any one of the following depending upon how we want to treat the number JA label jumm if AL above 127 unsigned JB label JG label jump ii AL below 127 unsigned jump if AL greater than 127 signed 52 Windows Assembly Language amp Systems Programming JL label NEG instruction jump if AL less than 127 signed This can be a point of confusion for novice programmers so be careful It is a good policy to stick with unsigned compares unless you have particular reason to do otherwise This is strictly for 2 s complement numbers it changes the sign of an operand For this example the result will be 127 in AL mov al 127 neg al mov al INC DEC instructions inc al dec al ADD SUB instructions add al 1 sub al 1 127 A useful point to note about the assembler is that you don t ever have to calculate the binary or hex negative 2 s complement number just put a minus sign
101. in front and the assembler will do the conversion The last line shows this INCrement DECrement These two do what their names suggest add 1 to an operand or subtract 1 from it Since we have specified an 8 bit operand in the examples below if INC goes beyond 255 FF hex then it will simply roll around and start from zero Ditto but the opposite for DEC Recall from the above notes that ADD SUB arithmetic instructions don t know whether your operands are 2 s complement or unsigned numbers that interpretation is up to you The size of the operands are important in these calculations and the instruction determines that from the operands themselves SUB works just like CMP setting the same flags and so can be followed by a conditional jump but the subtraction is not hypothetical the result of the subtraction is left in AX 27 27 These instructions can handle numbers bigger than 16 bits Of course so can the 386 since it has 32 bit registers but for now I ll assume I only have 16 bit registers and I want to add numbers that could possibly have a 32 bit result add ax cx add cx to ax result in ax ade bx dx Fad dx to bx with carry ADC SBB instructions DAA DAS Basic Assembly Language 53 For this example we have two 32 bit values in BX AX and DX CX The two lower halves are added leaving the result in AX The ADD instruction will set the carry flag if the unsigned result is greater than the
102. instruction ignore count register memory AL AX EAX immediate destination string source string segment register Noi uel Number preceding item indicates number of bits Abbr NAME CF Carry flag PF Parity flag AF Auxiliary carry flag ZF Zero flag SF Sign flag TF Trap flag IF Interrupt enable DF Direction flag OF Overflow IOPL I O privilege level NT Nested tank flag RF Resume flag VM Virtual 8086 mode Note that some coprocessor flags are also indicated in the tables The legend is IE Invalid UE Underflow PE Precision DE Denormalised ZE Divide by zero OE Overflow 369 370 Windows Assembly Language amp Systems Programming Format Instru ction Description gt 0 Flags affected 86 286 386 ARA ASCII adjust AL after add AF CF AAD l eS ASCII adjust before divide SF ZF PF ee AAM ASCII adjust after multiply SF ZF PF AAS ASCII adjust after subtract AF CF nas ADC accum imm ADC mem imm ADC mem reg ADC reg imm ADC reg mem ADC reg reg Add with CF OF SF ZF AF PF CF ADD accum imm ADD mem imm ADD mem reg ADD reg imm ADD reg mem ADD reg reg Add OF SF ZF AF PF CEF AND accum imm AND mem imm AND mem reg AND reg imm AND reg reg AND reg mem Logical AND OF 0 SF ZF PF CF 0 ARPL Adjust requested privilege level LE BOUND reg source Detect array index out of range None j BSF reg mem or
103. interrupts with example code TSRs What originally started me thinking about this topic was a problem some colleagues of mine at Edith Cowan University were having They wanted a Windows 3 0 application to sit in memory like a TSR Terminate and Stay Resident program logging external real time events while Windows was running other applications In other words they were asking for preemption Windows they concluded was not suitable so they chose OS 2 After some experimentation I discovered that it is very simple to create a Windows application that behaves just like a DOS TSR and hook an interrupt vector yet be operating in Protected mode and be in every respect a normal Windows application Hooking an interrupt vector means to change the entry in the interrupt table refer back to page 33 to point to the new TSR In DOS it was very common for a TSR to hook INT 16h the code that follows also hooks this vector but note that Windows doesn t use INT 16h for keyboard input so it doesn t matter what damage we do to this vector An interrupt can be either a hardware or a software interrupt a good DOS programming book will clarify the distinction but basically a hardware interrupt occurs as the result of an external event via the Interrupt Controller chip and maps to various reserved entries in the interrupt table Software interrupts are invoked from a program by the instruction INT n where n
104. investigations Note that there may be some upper memory blocks that are global also If you want to investigate this topic further note that instantiation can be forced For example a device driver can be actually copied to all VMs rather than all VMs mapping back to the original Thus the memory illustrated in Figure 15 2 is configurable which is why you should take it as a guide only Instantiation can be forced by an entry in the SYSTEML INI file This works at the level of files and you can find how to do it from Microsofts documentation on the SYSTEMLINI file However it is also possible to force instantiation at a lower level for example certain data areas Refer to Writing Windows Device Drivers by D Norton Addison Wesley page 170 Mapping the 4 3G Linear Address Space of a VM to Physical Memory I have introduced the question of how the VMs map between each other and physical memory from the point of view of the first 1M region but what of the entire 4 3G of linear memory Figure 15 2 shows the mapping below 1M that is common between VMs However each VM including the system VM can have its own Protected mode so each can address a linear address space of 4 3G To give a complete picture I have elaborated below on the question of common mapping of physical memory In each VM if the CPU is in Protected mode not V86 mode the selector offset address is translated via descriptor tables to a linear address This
105. is described in Chapter 1 In the case of 286 based Windows Standard mode the linear address is also the physical address and there are no virtual machines though there can be The linear address in this case is 24 bits and can address 2 24 physical locations Windows Enhanced 386 based mode uses the extra step of paging thus the linear address no longer corresponds with the physical address However this 32 bit linear address gives the 4 3G linear address space we are talking about Paging will map it into a much smaller physical memory space First a note on the first1M of a VM The system VM s V86 portion being the first created is mostly below the physical 1M The mappings of Figure 15 2 on page 343 apply but the virtual addresses such as the free RAM within the 640K map directly Advanced Systems Programming 345 to the actual physical conventional memory The free virtual conventional RAM of other VMs will be physically in extender memory Figure 15 2 Global memory below 1M 0 System Virtual Machine IVT BIOS data area DOS data area papas meme m In built device drivers j VM number 1 The shaded areas are mapped back to the original and are not copies Thus this code and data is global across all VMs Protected mode Programs that load within a virtual machine are local to it In this p RER meen e e Tota TCOMMAND program Free RAM example t
106. is the ISR Interrupt Service Routine that is the end result Wherever the interrupt originated control should end up there I want this ISR to behave much like the ISR introduced in the previous chapter that is to post a message to the main window A Protected mode ISR is shown back on page 262 illustrating how to post a message Because the WinApp has hooked INT 60h in the system VM any software interrupt within the system VM while the CPU is in Real mode will cause execution of the Protected mode ISR run time portion of the WinApp You can see in the DOS TSR that this was very simply done by an INT 60h instruction Entry to When control is passed up from Real to Protected mode the ISR the ISR is entered with certain registers loaded DS SI Real mode SS SP ES DI Real mode call structure The call structure is that same data structure containing the Real mode register values Return from the ISR is by an IRET but the data structure is modified as appropriate At exit the registers ES DI must be pointing to the data structure because the DPMI handler will put whatever is contained in the structure into the Real mode CPU registers Real Mode Access 28 5 Exit from For example if we want the ISR to chain to the old ISR we need the ISR to get the old vector and put it into CS IP in the data structure jend of ISR mov ax cs segmentreal mov eS di csl1 ax mov ax cs offsetreal mov eS di ip1 ax
107. learn Windows programming as well as a look under the hood for those with Windows programming experience but with an urge to know more You can also use it to learn assembly language By the very nature of tackling a topic from a fundamental point of view the nut and bolts if you like the beginner can develop very concrete concepts on which to build When you have a grasp of what is going on underneath a lot of what happens on top makes more sense Therefore a beginner can progress to being advanced in the same book with a solid foundation of understanding This chapter is an introduction to the basic principles of Windows followed by a complete assembly language program in Chapter 4 and beyond don t worry if the skeleton program looks intimidatingly long this is done to show the nitty gritty of how an assembly language program works Chapter 5 shows you how to write an assembly language program that is almost as short as the same thing written in a high level language such as C 69 70 Windows Assembly Language amp Systems Programming Other references Skeleton program DOS versus Windows Programming So just how different is Windows from DOS Below I have summarized some new concepts you ll need to come to terms with If you come across a reference to a DOS concept or programming method that you don t understand refer to a good DOS assembly language book There are a dozen or
108. limit FFFF hex ADC means ADd with Carry and adds the carry flag bit plus DX to BX with the result in BX Thus the total result is in BX AX For subtraction of 32 bit numbers the principle is the same and there is an appropriate instruction SBB SuBtract with Borrow For addition and subtraction of BCD numbers you need to use DAA and DAS The operation of DAA Decimal Adjust for Addition is shown pictorially in Figure 2 6 It corrects the result of adding two BCD packed decimal values Operates on the AL register If the rightmost four bits of AL have a value greater than 9 or the half auxiliary carry flag is 1 DAA adds 6 to AL and sets the half carry flag If AL contains a value greater than 9Fh or the carry flag is 1 DAA adds 60h to AL and sets the carry flag Figure 2 6 Decimal arithmetic 85 hex these numbers are 50 hex these numbers are 20 hex packed BCD 21 hex packed BCD app LAS ey sus opey Fag E Fiag 2 MUL DIV IMUL IDIV mul bl mul bx DAS Decimal Adjust for Subtraction is the opposite of DAA After subtracting two numbers perform DAS operation on AL If the rightmost 4 bits have a value greater than 9 or the half can y flag is set DAS subtracts 6 from AL and sets the Carry Flag There are two groups of multiply and divide MUL and DIV for unsigned numbers and IMUL and IDIV for signed numbers One problem we have with multiply is that two 16 bit operands can produce a re
109. ll find 2 bits that hold the Input Output Privilege Level IOPL Your application must have a privilege level numerically equal to or less than this to be able to perform I O With Windows the IOPL field is set to zero most privileged However it is possible for the operating system to give permission for certain I O to occur even though the application doesn t have the right privilege I O access involves use of the IN and OUT instructions and control of the interrupt flag by CLI and STI Windows 3 0 runs WinApps at level 1 DOSApps at level 3 and DLLs at level 1 Windows 3 1 and later run all three at level 3 32 Windows Assembly Language amp Systems Programming PUSHF POPF Changing LDTs Task State Segment instructions The interrupt flag is in the FLAGS register and when cleared prevents hardware interrupts from occurring If the application has sufficient privilege to perform direct I O it can also set and clear the interrupt flag Although a Windows program does not have the privilege of direct I O Windows does allow it to an extent If I O is attempted the CPU goes to a Windows error exception routine which does have the privilege to do what it wants the routine allows CLI and STI clear or set interrupt flag instructions but does not let PUSHF or POPF instructions affect the interrupt flag This is something to be aware of and a possible source of incompatibility with old DOS code It also means th
110. mem imm SUB mem reg SUB reg imm SW reg mem SUB reg reg Subtract Ob SF GE ARE PPE CE TEST accum imm TEST mem imm TEST reg imm TEST reg mem TEST reg reg AND function to flags OF 0 SF ZF PF CF 0 VERR Verify read access ZE VERW Verify write access ZE WAIT Wait for 80X87 None XCHG accum 16 reg XCHG mem reg XCHG reg reg Exchange None XLAT sourcetable Translate byte None XOR accum imm XOR mem imm XOR mem reg XOR mem reg XOR reg imm XOR reg mem XOR reg reg Exclusive OR OF 0 SF ZF PF CF 0 Instruction Set of the 80x87 Mathematics Coprocessor Refer beginning of Appendix A for legend Format Instruction Description Flags affected 87 287 387 F2XM1 2 ST 0 1 UE PE FABS Absolute value IE FADD dest source Add real IE DE OE UE PE FADDP dest source Add real amp pop IE DE OE UE PE FBLD source Packed decimal BCD load IE FBSTP Packed dec BCD store amp pop PCHS Change sign IE FCLEX FNCLEX Clear exceptions None FCOM source compare real IE DE FCOMP source compare real amp pop IE DE FCOMPP compare real amp pop twice IE DE FCOS Cosine Instruction Summary 375 FDECSTP Decrement stack pointer None FDISI FNDISI Disable interrupts None FDIV dest source Divide real IE DE ZE OE UE PE FDIVP dest source Divide real amp pop IE DE ZE OE
111. mov bx 05C5h mov al bl out 42h al mov al bh out 42h al in al 61h or al 3 out 61h al pop eax firstly let s hook anything port 200h and show a generalised handler mov edx 200h mov esi OFFSET32 My _VDEMOD_Hook VMMCall Install_IO Handler now let s prevent printing mov edx 3BDh lpt status mov esi OFFSET32 My VDEMOD_lpt_Hook VMMCall Install_IO_Handler mov edx 379h lpt status mov esi OFFSET32 My_VDEMOD_lpt_Hook VMMCall Install_IO Handler mov edx 279h jlpt status mov esi OFFSET32 My_VDEMOD_lpt_Hook VMMCall Install _ IO Handler mov edx 3BEh lpt control mov esi OFFSET32 ctrl VDEMOD lpt_Hook VMMCall Install_I0_Handler mov edx 37Ah lpt control mov esi OFFSET32 ctrl_VDEMOD_lpt_Hook VMMCall Install _ IO Handler mov edx 27Ah lpt control mov esi OFFSET32 ctrl VDEMOD_ lpt_Hook VMMCall Install_I0_ Handler xor eax eax mov VDEMOD_Owner eax no current owner Advanced Systems Programming 355 IFDEF DEBUG Trace_Out VDEMOD installed ENDIF ele ret EndProc VDEMOD Device Init VxD_ICODE_ENDS In the above code Ive used a VMMCALL macro rather than inserting INT 20h directly Install_IO_Handler is one of those low level VMM services This hooks the actual physical port so if the requirement is to block printing this will do it VDEMOD Device Init is the initialisation routine and VDEMOD _ Control tells Windows where it is see below I have started the beeper above and
112. new make routine can become part of WINASMOO INC along with the new class First here is the final program WINASMOO ASM gt WINASMOO EXE INCLUDE WINDOWS INC INCLUDE WINASMOO INC IDM QUIT IDM_ABOUT DATA EQU 200 EQU 201 Program Design 173 windowl WINDOW szclassname WINASMOO sztitlename 00 Demo paint wlpaint create wlcreate command wlcommand createstylehi WS_OVERLAPPEDWINDOW WS CLIPCHILDREN char wlchar sziconname icon 1 controll CONTROL szclassname BUTTON sztitlename OK x_coord 20 y coord 40 wwidth 30 wheight 20 hmenu IDOK createstylehi WS CHILD WS VISIBLE createstylelo BS_PUSHBUTTON CODE kickstart lea si windowl addr of window object call si make PASCAL si make the window lea si controll call si make PASCAL si make child window ret wlpaint PROC PASCAL LOCAL hdc WORD LOCAL paintstructa PAINTSTRUCT lea di paintstructa call BEGINPAINT PASCAL si hwnd ss di mov hdc ax call SELECTOBJECT PASCAL ax si hfont call TEXTOUT PASCAL hdc 10 20 cs OFFSET outstring 16 call ENDPAINT PASCAL si hwnd ss di ret outstring DB Demo 00 Program wlpaint ENDP wlcreate call GETSTOCKOBJECT PASCAL OEM FIXED FONT mov si hfont ax ret wlcommand cmp WORD PTR si lparam 0 lo half 0 if a menu select jne notmenu cmp si wparam IDM QUIT Is Quit selected jne notquit call si destroy ret notquit cmp si wparam ID
113. not everyones cup of tea It may be justified for developing device drivers and other low level work and yes weird people like me do put large applications together entirely in assembly Most of my work involves close interaction with hardware and or operating systems so I suppose I would be classified as a systems programmer However even systems programmers tend to use C depending on what operating system they are using and on just what kind of systems level work they are doing Really this chapter presents a certain philosophy and is not to be taken as the truth engraved in stone Use these ideas as food for thought The new kid on the block is GOOFEE diagrams which I developed GOOFEE is a visual analysis design and implementation methodology that is unique It is a truly unified wholistic approach targeting embedded systems Checkout my book Flow Design for Embedded Systems R amp D Books Miller Freeman USA 1997 The R amp D Books site on the Internet is http www rdbooks com My research site is http www goofee com One out of many on line bookstores is http www amazon com GOOFEE is not yet a 100 visual development tool but I wanted to mention it in case anyone is interested True 100 VPLs are rare indeed What is there LabView Programming LabView is at least as powerful as any text based language and has evolved since 1986 into a very mature and sophisticated product
114. of Windows apps Code conversion from MASM to JASM Resource files e The fields of the structures mostly become 32 bits e FAR addresses become the same as NEAR addresses and are 32 bits The OFFSET prefix in an instruction will load the 32 bit address of a static data item and you do not need to worry about the segments e All stack pushes and pops are 32 bit e Values returned from functions are in EAX e Note that the Win32 API is a blend of C and Pascal calling convention That is stack cleanup is performed by the function but parameters are pushed right to left Please note that the 16 bit API pushes parameters left to right However using the high level procedures you do not need to worry about this When using Turbo Debugger you will need to be aware of this fact though For example in GetMessage orrser 2 gets pushed last When I first converted a MASM6 program for TASMS it assembled and linked but crashed when execution got to CreateWindowEx I paid closer attention to the skeleton example supplied with TASMS even though it is written for TASM4 I made a couple of changes and it now works and is rock solid though Im not sure which change was the culprit Notice that there is an ENDS directive at the very end of the program You could experiment and see what happens if that is left off I never needed it for MASM programs The rest of the program looks very much like a MASM6 program and TASMS also a
115. of the current IP 8 bit signed offset NEAR within the current segment 16 bit offset or FAR in another segment 32 bit segment offset In light of this take a closer look at that example MOV instruction BX is a 16 bit register while the content of ptr4 is DWORD 32 bit In other words a type mismatch The assembler will pick this up as a possible error and will tell you SO Any data values you define must have a size that matches the register mov Ax val6 would not work if val6 was defined as val6 DB 0 Get the idea The above code shows a solution overrides We have already looked at the overrides OFFSET and SEG now you are seeing WORD PTR This is a size override A syntactical note here in front of PTR we can place BYTE WORD DWORD NEAR or FAR as appropriate The example using WORD PTR tells the instruction to ignore the size type of the operand and instead treat it as being of size WORD This override is encoded by the assembler into the instruction op code and at execution time the override only applies to that instruction But if ptr4 contains a 32 bit value and by means of the override we are going to stuff it into a 16 bit register what will actually happen In the code above I show two MOV instructions with 64 Windows Assembly Language amp Systems Programming WORD PTR override The first will grab the lower 16 bits of ptr4 while the second will grab the higher 16 bits Order
116. of the structure comprises various data associated the WINDOW class with the window Here are explanations hwnd handle of this window wmessage the message sent to this window wparam lparam data associated with the message classstyle parameter used by REGISTERCLASS sziconname ditto What will look like when iconized szcursorname ditto What cursor like over window hbrbackground ditto Color of client area szclassname ditto ASCIIZ name this class of window sztitlename param used by CREATEWINDOWO ASCIIZ title appear at top of window hmenu ditto Menu or child identifier hwndparent ditto Handle of parent window wheight ditto Height of the window wwidth ditto Width of the window y_coord ditto Top left y coordinate x coord ditto Top left x coordinate createstylelo appearance features of window createstylehi ditto hfont application specific 162 Windows Assembly Language amp Systems Programming Creating multiple windows WinMain is hidden inside the Include file So override any of these parameters to make your window look and behave exactly as you want You are not limited to just one window As well as being able to have multiple instances of your program quite happily sharing the same screen any one instance can have multiple windows It is simply a matter of declaring another instance and calling make Make doesnt have to be called in the kickstart routine though that s where you would create the ma
117. picture Have another look at Figure 15 3 Each diagram or code module has a front panel which is a window through which all inputs and outputs travel Note however that this front panel may or may not appear at execution time Think of it as a handy development aid since it gives you total control over the diagram for testing purposes and interactive monitoring while executing Look higher and you will see that there is an icon that has input and output terminals which all go to and from the diagram via the front panel This icon makes the diagram into the equivalent of a subroutine or procedure and is a software object that can be reused with the greatest of ease An important point to note about Figure 15 3 is that you are seeing it in black and white when in fact it is in full color and all wires clearly show the data types they carry Furthermore LabView will not allow a connection if the data types are incompatible also note that most built in LabView icons are polymorphic meaning that they will accept almost any data type A LabView program can be composed of a hierarchy of icons That is the top icon in Figure 15 3 is itself composed of icons wired into a diagram which may in turn be composed of underlying diagrams and so on Code interface nodes Dynamic link libraries Reference source Flowchart programming Advanced Systems Programming 363 Any one of these icons could be a program that has
118. plus other status information Since version 1 0 of DPMI has more features than version 0 9 this test is necessary if you want to use the extra features of v1 0 Note that Windows 3 x and 95 only support DPMI v0 9 refer to page 198 I have written the code in this chapter for v0 9 So again this test is not really required I have stored all of the flags as static data to be used as needed by the rest of the program Addressing Segments Assuming that DPMI is up and running which it should be under Windows you are ready to start doing interesting things One of your objectives is to access real memory directly That is you hunger for the good old days when you could write directly to the video RAM not via some tortuous method using GETDC TEXTOUTQ and RELEASEDC with a hundred messages to worry about You want control slobber slobber and you want speed You may even be totally retrograde and want to run your Windows program with the screen in text mode horror Remember good old text mode It was good enough for most things and even did quite a good job at graphics using the IBM graphics character set The MDA Monochrome Display Adaptor only has a 4K video RAM with the result that screen redrawing is instantaneous Forget about delays with text mode This text mode topic raises an interesting side issue There are a lot of other retros like me out there and there is even a special product available for those who
119. point in the program or the starting address of an ASCII string I gave an example of how to define a mov AX mov AX OFFSET override SEG override mov AX Basic Assembly Language 59 text string above and labelled it str1 The assembler equates strl to the starting address of the string strl loads contents OFFSET strl loads address Unfortunately because the assembler has assembled the first MOV instruction as non immediate addressing the first MOV here would only load the first two ASCII characters me into AX two characters are fetched because the destination is AX which is a 16 bit register This is not what we want We want to load the starting address of the string into AX What we have to use is an override directive that forces the instruction into an immediate addressing mode Thus the second example will load the actual operand into AX which is the required address Note too that you can get the segment value where that string is stored which would normally be the data segment by this override SEG strl load segment address OFFSET and SEG only work for static data that is data that is defined in the data or code segments It is possible to have dynamic or automatic data that is created during execution on the stack or heap getting the addresses of this data involves other techniques discussed on page 60 and in Chapters 4 and 5 Pointers Data labels can also be pointers Th
120. privilege levels OPL field IN OUT CLI and STI l CPU Architecture 31 So what happens if your program writes directly to video RAM at segment B800 This is up to the operating system which most likely will create virtual screens for each task setting them up anywhere it wants to in RAM Contention Issues There are various things to think about under this heading but I have at this stage just addressed the issues of privileges I O and task switching The topics are brought up at various points through the book so look in the Index for other page references Privileges The dpl field in the descriptor defines the privilege level of that segment Also you will see back on page 27 Figure 1 12 that the selector has a requested privilege level rpl Because it is a 2 bit code there are four possible levels zero being the most privileged The kernel of the operating system will operate up here zero while your lowly program will reside at a lower privilege level Your program s level is basically reflected in what the rpl is set to and this must be numerically equal to or less than the segment s dpl to allow access to that segment otherwise the CPU exits to an error routine and the dreaded UAE Unrecoverable Application Error dialog box appears and that s the end of your program I O Privilege Privilege levels do have some impact on I O If you look at the FLAGS register see page 244 you
121. program rather than as a separate module Prototypes The program at the end of this chapter can be assembled under MASM6 or more correctly ML As the product is not terribly compatible with earlier MASMs Microsoft has renamed it though you do have the option of switching on compatibility with version 5 1 MASM6 has developed features that make it look more like C most notably the use of prototypes These are skeleton declarations of a procedure which you place at the beginning of the file and are used by the assembler for syntax and type checking These are best illustrated by an example and an excellent example presents itself in the use of INVOKE Borland introduced the equivalent with TASMS5 though they have given it a different name PROCDESC See Chapter 13 page 308 MASM6 CALL is definitely low level so to call Windows functions in the convenient manner that we have become accustomed to in this chapter we need to use INVOKE instead In fact TASM3 s high level CALL is quite primitive alongside the sophisticated INVOKE as youll see The first line shows the call to MESSAGEBOX as we would do it with TASM TASM 3 00 high level call call MESSAGEBOX PASCAL hwnd ds OFFSET szabout ds OFFSET sztitle MB_OK MASM 6 00 high level call INVOKE MESSAGEBOX hwnd ADDR szabout ADDR sztitle PROTO declaration MB_OK INVOKE does the same job However if you put it in as shown it wont work becau
122. push es push fs push gs mov default0esp esp save default ring 0 stack mov default0Oss ss setup a new stack mov ax 30h mov sS ax lea esp ring0stack 1996 add esp flatdatalin calc Flat linear addr Sti rvina i ds works here but let s replace it with FLAT ds mov ax ds use fs to access data in our prog mov f sS ax F mov ax 30h Flat ds mov ds ax mov e S ax mov gs ax example of calling a VMM service int 20h DW GET_CUR_VM_HANDLE es 1 DW VMM DEVICE ID p u H example of using a 386 privileged instruction SEE CX get task tss register selector 304 Windows Assembly Language amp Systems Programming xexample of another call to the VMM yee parameters are passed by stack so push them on pushd 0 get its descriptor out of gdt pushd 0 pushd ecx int 20h i DW GETDESCRIPTOR gt DW VMM DEVICE ID add esp 12 mov eCx eax zero in eax and edx if error or ecx edx jz errori jmp bypassl errorl do something here bypassl restore default ringO stack oul make sure mov ss fs default0Oss mov esp fs default0esp POP gs pop fs POP es POp ds popad opfd ae f RINGOFUNC ENDP _TEXT2 ENDS END Because the default stack is very small I have replaced it with another that physically exists in the data segment of ASMRINGO Execution enters RINGOFUNC with DS still set to the data segment of ASMRINGO but I have moved it in
123. question but Ill say you ve got it You try to perform a CALL to that address but the CPU intervenes since you are at lowly ring 3 and passes control to Windows which informs you that there has been a general protection error The way around this problem is to create a call gate Normally only the operating system ring 0 is supposed to be able to create a call gate but we can do it from ring 3 using undocumented features I wonder whether this loophole will be closed the technique has been published in Microsoft s own Microsoft Systems Journal which would tend to give it some authority I suppose and the loophole remains in Windows 95 32 Bit Ring 0 293 A call gate is 8 bytes and can be an entry in the LDT or GDT just like a descriptor However it has a different structure to a descriptor as Figure 12 2 shows Fieure 12 2 Detail of the call gate CALL GATE OFFSET 7 Low part of the offset to be called bits O 1 5 0 Offset Linear starting address of the segment Offset_8 15 da bits 0 23 Selector_0_7 BIT cee Te O 3 Param_count These bits must be zero Selector_ 8 _15 BIT lt 0 3 Type 4286 call gate C 386 4 App_system 5 6 DPL 7 Present Offset_24 3 1 High part of the offset to be called bits 16 31 Actually what distinguishes this as a call gate and not some other kind of gate is the Type field The value Type 4 means that it is a call gate to a 16 bit 286 segment while a v
124. range of sub functions available under DOS but Windows adds some extra functions If you look in any DOS programming book you wont find anything on these extra functions nor on INT 3 lh Even Microsofts own reference bible The Programmers PC Sourcebook second edition by Thorn Hogan USA 1991 has nothing on these services Reference You have to scratch around in strange places to find the sources information This book brings much of it together and where it does not I give the appropriate reference Microsofts Device Development Kit DDK has reference material on DPMI and I think their Archive Library CD ROM has also Obtaining these requires that you join the Microsoft Developers Network MSDN and this is where Microsoft has us over a barrel they want quite a lot of money for membership You can find a lot of information on the Internet For example a site with lots of links for developers is http www r2m com windev Another site with DPMI reference information is http www delorie com djgpp doc DPMI First I will fit DPMI into its place in the overall scheme of things overview the meaning of life and all that before getting into a look at the standard BIOS and DOS services DPMI enables DOS applications to access the extended memory of PC architecture computers while maintaining system protection It also defines a new interface via software interrupt 31h that Protected mode applications use to
125. reg reg Bit scan forward ZF BSR reg mem or reg reg Bit scan reverse ZF BT Test bit CF BTC Test bit and complement CE BTR Test bit and reset CF BTS Test bit and scan CF CALL 16 memptr CALL 16 regptr CALL 32 memptr CALL farproc CALL nearproc Call control transfer None except if task sw CBW CWDE Convert byte to word word to double word None CLC Clear CF CF 0 CLD Clear DF DF 0 Chl Clear IF EE 19 CLTS Clear task switched flag TS 0 in CRO reg CMC Complement CF CF CMP accum imm CMP mem imm CMP mem reg CMP reg imm CMP reg mem CMP reg reg Compare OF SF ZF AF PF CF CMPS rep deststr sourc CMPS deststr sourcestr Compare byte word or double word string OF SF ZF AF PF CF CWD CDQ Convert word to doubleword dw to qw None DAA DAS Decimal adjust after add subtract SF ZF AF PF CF DEC mem Decrement OF SF ZF AF PE DEC reg Decrement OF SF ZF AF PE DIV 16 mem DIV 16 reg DIV 8 mem DIV 8 reg Divide None ENTER 16 imm 0 ENTER 16 imm 1 ENTER 16 imm level Enter procedure None ESC imm mem ESC imm reg Escape to external device None HLT Halt None IDIV 16 mem IDIV 16 reg IDIV 8 mem IDIV 8 reg Signed integer divide None IMUL 16 mem IMUL 16 reg IMUL 8 mem IMUL 8 reg Instruction Summary 371 Signed integer multiply OE MEE IMUL destreg 16 reg imm IMUL destreg mem imm Signe
126. return character the line prints Since Windows uses its own special printer drivers for output the question naturally arises about whether you can use the old DOS service Will it work Will there be a clash The answer is that it works fine but yes clashes are possible However for every problem there is a solution including that of contention over resources Another qualification that needs to be made is that Microsoft has taken the opportunity with 32 bit applications to restrict BIOS DOS and other low level access This will be explained as you read ahead The advent of Windows 95 does not mean that DOS is dead Even though Windows 95 does not identify DOS as a separate product still it is there You can start the PC with the DOS prompt or launch a DOS box from Windows just as before Its really more of the same thing despite the Windows 95 publicity hype There are a number of issues with regard to how DOS lives alongside Windows some of which I have gone into in Chapters 11 and 14 BIOS and DOS Services Overview This is a mysterious gray area very poorly documented by Microsoft Although Windows runs in Standard or Enhanced Protected mode most BIOS and DOS services still work with various caveats DPMI Apart from the standard services Windows also supports a special group of DOS services called the DOS Protected Mode Interface DPMI These consist of some INT 2Fh services and INT 3lh services INT 2Fh has a
127. so introductory Windows programming books that could be used to compliment this book not the least being Microsoft s own Microsoft Windows Software Development Kit Reference Vol 1 available separately from the SDK You do need a book with in depth coverage of the Windows functions and again Microsoft s own Microsoft Windows Software Development Kit Programmer s Reference Vol 2 is excellent The next chapter puts together a simple skeleton program but before we launch into that let s consider some of the conceptual differences involved The output on the screen will look different for Windows 3 x and 95 Figure 3 1 is what the skeleton will produce on the screen when running Windows 3 1 Figure 3 1 Output of skeleton program i SKELETON pROGRAM MA File This is a window amongst other windows with its own title system controls menu bar and demo message So a major conceptual difference from DOS is that our program doesn t output to just anywhere on the screen normally we are constrained to output only within our application s window or windows Interestingly another major difference is the role of the operating system Windows does a lot of housekeeping and looks after much of the usual upkeep of the window such as moving it around iconizing and resizing Event driven program structure Application queue Multitasking operating system Opening Windows 71 In fact Windows does ev
128. something with the message There is a callback function for each window that your program creates Callback Functions WndProc I said above that having got the message via GetMessage your program must then give it back by calling DispatchMessage Windows then sends the message to another part of your program known as a callback function In fact each window including windows called dialog boxes has its own unique callback functions The name I gave above WndProc is only a suggestion Unlike the main function which must always be called WinMain though this has become more of a convention only your callbacks can be called whatever you want There is a simple mechanism for informing Windows of the names of the callbacks so it can call them This is a C skeleton of a callback long FAR PASCAL WndProc hWnd message wParam lParam HWND hWnd window handle unsigned message type of message WORD wParam more information LONG lParam more information case logic to analyse message i ee user written message handling default message handling DefWindowProc hWnd message wParam lParam There is yet another twist The message getting a bit ragged around the edges by now with all that travel goes to the callback 80 Windows Assembly Language amp Systems Programming function which can then process it But the twist is that most messages are of no interest to your program
129. string instructions W B pos tix Basic Assembly Language 47 Some notes on this e In the case of COM programs CS DS SS so the question of override doesn t arise normally With a EXE program data could be kept in the code segment as long as execution jumps around it but note also that OS 2 and other operating systems that operate the 286 and 386 CPUs in Protected mode may be very unhappy with data kept in the code segment s e Sometimes data is kept in a segment pointed to by ES or FS and GS in the 386 so ES override might be useful in this situation The BP register although a general purpose register is treated by the assembler as an offset into the stack segment SS by default Thus if you want to use BP to access data in segments pointed to by DS or ES an override is required String Instructions This group of instructions are designed for moving blocks of data from one place in memory to another and some of them are for searching through and comparing blocks of data The word string does not necessarily imply text but any block of data Mostly you will use the string instructions responsible for moving data around such as MOVS LODS and STOS Basically you have the source block in one part of memory and the destination somewhere else and you have to set certain registers to point to these source and destination areas before using the string instruction The string instructions have an impli
130. szhdg MB_OK notabout ret notmenu ret szmsg DB Created by Barry Kauler 1992 0 szhdg DB Message Box 0 ret END What you will recognize from this is all of the essential functionality from the skeleton of Chapter 5 without the red tape Overriding In the data segment I have created an instance windowl of the class structure WINDOW Now if I had just ended that line with defaults the window would have the defaults as defined in WINASMOO INC However any of the defaults can be overridden to create any kind of window You need to know 1 56 Windows Assembly Language amp Systems Programming Overriding PAINT message COMMAND message override PROC ENDP syntax notes precisely how to do this of course but for now just look at the overrides in the above example I have given the window a class name of WINASMOO and I have given it a title to appear in the title bar at the top of the window If you remember back to Chapter 3 and in particular page 77 youll know that whenever anything happens over your applications window while the window is active such as a menu item being selected or key being pressed then Windows will send a message via the message loop in WinMain to the window callback function It is then up to the callback function to process the message Overrides WINASMOO INC handles all the messages in a default manner but should you want to process any message just put in an override
131. that has the system files on it DOS prompt or Windows Boot Record 10 SYS MSDOS SYS Booting to DOS or Windows CPU Architecture 3 The end result of the above sequence is that COMMAND COM is loaded and executed at which point in time you will see the DOS prompt which usually shows the current drive followed by a gt character For example A gt Or WIN COM executes which loads the rest of Windows In the case of Windows 3 x COMMAND COM loads first optionally followed by WIN COM However Windows 95 bypasses COMMAND COM The System Files To boot DOS or Windows requires a Boot Record on the system disk The boot program in ROM on the PC s motherboard looks for the presence of the Boot Record part of which is a program that is then loaded into RAM and executed When loaded and executed the Boot Record checks to see if the system files are stored on the disk It looks for and loads into RAM the files IO SYS and MSDOS SYS During the loading process the files CONFIG SYS and AUTOEXEC BAT are looked for and referenced if they exist They help to configure the system and create a personalised environment for the user IO SYS contains extensions to the ROM BIOS These extensions may be changes or additions to the basic I O operations and often include corrections to the existing ROM BIOS new routines for new equipment or customised changes to the standard ROM BIOS routines This file contains the DOS version
132. the application because executing that interrupt from some other application will cause the CPU to try to execute a service routine that is no longer there In fact it will crash rather rudely It is possible to create a window for the program but keep it invisible to prevent accidental closure or unhook it before closing See an example of unhooking on page 260 Is that all there is to it Yes Even the old DEF file can be used and you can have MOVEABLE and DISCARDABLE segments It is not necessary for the CODE and DATA segment statements in the DEF tile to have FIXED qualifiers FIXED forces Windows to leave the segments at a fixed place in memory rather than moving them around as it normally does You would think from the way TSRs are designed under DOS that a resident interrupt handler should be FIXED but not with Windows If the operating system determines that the segment referenced via the IDT is not actually in memory then it will get it back and update the descriptor If you want modify the DEF file as follows PRELOAD FIXED PRELOAD FIXED Note that it possible to have an application without any window at all Since all messages usually are posted to a window this requires special consideration For example POSTAPPMESSAGE will post a message to an application without a window and leave the message s hWnd parameter NULL Related issues Accessing data in the ISR Real Time Events 253 Specifying FIXE
133. the data segment with information about the stack WAITEVENT The parameter zero when supplied to WAITEVENT clears the INITAPP event that started the current task INITAPP initialises the queue and support routines for the application WINMAINQ Below is the rest of the code segment which has WINMAIN and the callback function SKELETONPROC Functions that are to be called by Windows must be declared as PUBLIC CODE PUBLIC WINMAIN WINMAIN PROC NEAR entry point from Windows Parameters passed on the stack will be as per the listing on page 77 and will have been pushed on from left to right with the return address pushed on last Figure 4 1 You can check this against the startup code above push bp Save BP so can use to access params mov bp sp BP will now point to top of stack sub sp 46 mov stack to free region Figure 4 1 Stack at entry to WinMain Stack Pointer SP Base Pointer BP register points here This is what BP 4 the stack looks BP 6 like at this point in the BP 10 program BP 12 7 hInstance 4 see next page The Bare Bones 99 cmp WORD PTR bp 10 0 hPreviInstance jne Prolog code First instance handling 0 if no previous instance createwin One important thing to notice from Figure 4 1 is that after the prolog code BP points to the parameters so that the program has ready access to them while SP has been moved away so that the stack
134. the game you should be able to follow through the logic of DOSTSR ASM Note that INT 60h in the IVT is hooked by the WinApp and is where the Protected mode ISR is located INT 61h is hooked by DOSTSR itself merely to pass its own forwarder address to the same DOSTSR in another VM Paradoxically there is only the one TSR and they only appear to be in different VMs all virtual addresses map back to the same physical addresses However the DOSTSR while executing in another VM does not necessarily know the segment offset address of the forwarder in the system VM Something else you should pay some attention to when developing robust code is the possible contention if more than one VM wants a piece of the action at the same time That is programs in two different VMs enter the TSR and work on the same data Crash Anticipate this and either design the data to be reentrant or force instantiation by an entry in SYSTEM INI or use INT 2Fh 1605h to create instantiation of specific data areas see Writing Windows Device Drivers by Daniel Norton Addison Wesley 1992 page 170 Or prevent reentrancy as I did with my demo program See earlier notes on the problem of reentrancy on page 323 330 Windows Assembly Language amp Systems Programming Device drivers for DOS and Windows DOS TSRs and Windows TSRZ2WIN example code DOS to Win Device Driver TSR This book so far has dealt with various issues of how a DOS program and TSR
135. the menu will jne notwmcommand produce jmp xmenu this message notwmcommand cmp ax WM LBUTTONDOWN one of many mouse messages jne notwmibutton im xbreak notwmlbutton cmp ax WM_CHAR message that a key pressed texchar defhandler Default handling of messages invoke DEFWINDOWPROC ihWnd imessage iwParam ilParam jmp xreturn es ee o o we ee eH nn l Fe G M eB we Pe BH we cepeate invoke GETSTOCKOBJECT OEM FIXED FONT mov hOemFont ax handle to font jmp xbreak xquitmessage invoke POSTQUITMESSAGE O jmp xbreak xchar jmp xbreak Xpaint lea ax wax flan addr of paint structure invoke BEGINPAINT ihWnd ss ax mov hDC ax hDC display context required before can output to screen For this simple demo any redraw of the Window will cause output of our hullo world string High Level Assembly 135 invoke SELECTOBJECT ax hOemFont invoke TEXTOUT hDC 10 20 ADDR soutstring 11 lea ax s faxr addr of paint structure invoke ENDPAINT ihWnd ss ax jmp SHORT xbreak xmenu cmp WORD PTR ilParam 0 low half of 1Param jne xbreak test if a menu message cmp iwParam IDM_QUIT wParam jne notquit imp Xxquitmessage notquit cmp iwParam IDM_ABOUT jne xbreak no other menu items let s put up a message about this program invoke MESSAGEBOX ihWnd ADDR szaboutstr y ADDR sztitlestr MB OK ee ee we we we we ew ew ww
136. the name segments memory requirements and exported including callback functions of the application and is straightforward enough to write with a text editor All functions in your program that are to be called by another program must be declared asexported in the case of the callback function it is called by Windows The only function that doesnt need to be declared as exported is your WinMain Here is the RC file SKELETON RC define IDM QUIT 200 define IDM MES SAGE 201 skeleton MENU BEGIN POPUP File BEGIN MENUITEM Quit IDM QUIT MENUITEM Message JDM MESSAGE END END 90 Windows Assembly Language amp Systems Programming Menu bar You will be able to figure out what this RC file does by observing the execution of the program A menu bar with only one selection File drops down two menu items Quit and Message The next chapter has the same Hi there program but written using high level assembly constructs IDM_QUIT and IDM_MESSAGE are arbitrary labels assigned almost arbitrary values One of these values is passed within a message as an identifier to Windows if a menu item is selected Message Format WM_ Selecting a menu item generates a WM_COMMAND message COMMAND _ which is one of many possible messages that can be sent to the message callback It is a 16 bit value and also has other parameters notably wParam and lParam that constitute extra data attached to t
137. the physical memory if function unsuccessful set error code 8003h system integrity DPMI host memory region 8021h invalid value address is below 1 MB boundry AX Int 31h Function 0900h Get and Disable Virtual Interrupt State Disables the virtual interrupt flag and returns the previous state of the virtual interrupt flag Call with Ax 0 Returns Virtual interrupts disabled CF clear this function always succeeds AL 0 if virtual interrupts were previously disabled lif virtual interrupts were previously enabled 900h Int 31h Function 0901h Get and Enable Virtual Interrupt State Enables the virtual interrupt flag and returns the previous state of the virtual interrupt flag Call with AX 0901h Returns Virtual interrupts enabled CF clear this function always succeeds 0 if virtual interrupts were previously disabled if virtual interrupts were previously enabled AL Int 31h Function 0902h Get Virtual Interrupt State Returns the current state of the virtual interrupt flag Call with AX 0902h Returns CF clear this function always succeeds AL Q if virtual interrupts are disabled lif virtual interrupts are enabled Int 3th Function 0A00h Get Vendor Specific API Entry Point Returns an address which can be called to use host specific extensions to the standard set of DPMI functions DPMI 1 O clients should avoid use of this function Call wit
138. this below writes the pseudo text mode window on to the scrn mov ah 2 set cursor position mov dh 5 row 5 mov dl columns shr dl 1 centre cursor on screen mov bh vpage video page push dx save int 10h mov dx OFFSET sdirect 242 Windows Assembly Language amp Systems Programming mov ah 9 write a string to sern int 2ih pop dx restore inc dh next row mov bh vpage mov ah 2 push dx Save int 10h set cursor mov ah 9 write string Mov dx OFFSET sdir2 int pop dx restore inc dh next row on scrn mov bh vpage mov ah 2 int 10h set cursor mov ah 9 write string mov dx OFFSET sdir3 int 21h mov ah 2 restore cursor pos mov dax curpos mov bh vpage int 10h ret DATA mode DBO columns ne vpage curpos DW sdirect sdir2 ee ees ee wp o Reference sources http www VGA and SVGA 0 0 0 DB DB BIOS DOS O P DB e ssas ss obv n eooo l oeoo ohod lo l y M ou ll labd la Refer to a good DOS BIOS programming book for details on the video services A person by the name of Ralph Brown has compiled a detailed document on all of the interrupts and this can be located at various places on the Internet such as cs cmu edu afs cs user ralf pub WWW files html The above code for drawing the box isr particularly elegant there are a hundred possible ways but shows the idea One lovely feature of the BI
139. to be in every VM It will be but the IVT hook s appearance in every VM is what matters we want a DOSApp in another VM to pass control over to the copy of the TSR in the system VM which can in turn pass control up to a WinApp This may seem complicated but hopefully I can explain it clearly First consider the DOS TSR It will have to be loaded before Windows and will have to hook a vector in the IVT DOSTSR COM Resident program to pass control up to a WinApp 286 DOSTSR SEGMENT BYTE PUBLIC CODE ASSUME cs DOSTSR ds DOSTSR es DOSTSR ORG 100h begin jmp start Put any local data in here mode forwarder push es Save working registers push ds pusha sti enable interrupts unless you want a crash push cs routine entered with DS unknown pop ds want to addr local data To pass control up to a WinApp the WinApp has to provide its address selector offset in the IVT We must test if that has been done xor ax ax get current int 60h vector 278 Windows Assembly Language amp Systems Programming mov mov mov mov or jz int done60 popa pop DOP lret END Install portion es ax don t use int 21 35 as under si 60h 4 certain circumstances DOS bx es si may not be stable ax es si 2 ax bx it will be 0 0 if not hooked done60 if not don t forward to it 60h issue int 60h to call WinApp restore registers ds i es t
140. to set focus to current VM or VM ID to set focus to a given VM int 2Fh cmp al 0 je success 0 if focus is set The VMId parameter must either specify a valid virtual machine ID or must be 0 to specify the current virtual machine In Windows 3 1 the VMId of the system virtual machine is I The function returns 0 if it changes the focus successfully Interrupt 2Fh Function 4000h Enable VM Assisted Save Restore Directs the virtual display device VDD to notify the virtual machine VM application whenever the VDD needs to access the video hardware registers The VDD returns a value specifying the number and type of video modes the VDD supports when the VM application is in the background A VM application calls this function during its initialization Call with Ax 4000h Return value The return value is one of the following values if successful Value Meaning Olh No modes virtualized in background 02h Only text modes virtualized in background 03h Only text and single plane graphics modes virtualized 04h Only text single plane and VGA multiplane graphics modes virtualized OFFh All supported video modes virtualized Otherwise the function returns zero in the AL register if virtualization is not supported Comments When a VM application calls this function the VDD disables I O trapping of unreadable registers Thereafter the VDD calls Save Video Register State and Restore Video Register S
141. top value off the stack into a register or memory location Also PUSHF and POPF can be used to push the FLAGS onto the stack and pop them off Whoa This is a lot to think about I ve just stated above that there is a memory area called a stack that it is used by the CPU to store register values for interrupt and CALL instruction execution and it is used by the PUSH and POP instructions You may find it extremely helpful at this point to visualise what is happening Look at Figure 2 1 and examine the effect of the PUSH and POP instructions In Figure 2 1 you see two instructions PUSH and POP that you can use in your program You can push values onto the stack and take them off again why one reason is that it serves as a convenient temporary storage I also mentioned that the stack is used by the CALL instruction this is one of the transfer of control instructions and is described in the next section I mentioned that interrupts also use the stack again explanation is deferred Do not worry about these deferred explanations one thing at a time Examination of Figure 2 1 will give you an idea about what the stack is which is satisfactory for now Basic Assembly Language 39 Figure 2 1 Concept of the stack From a logical user s point of view the stack is like a bucket pushing a value on adds to the top of the bucket while popping takes off the top entry in the bucket PUSH IS SS s
142. version and not the other References to the SDK without specifically naming 3 0 or 3 1 apply to both 208 Windows Assembly Language amp Systems Programming Low level USER GDI KERNEL function summary I have used an asterisk if a function is not directly supported by 32 bit applications in Windows 95 optionally followed by a recommended 32 bit alternative I have used a if a function is unofficially available in the 32 bit Windows 95 API a amp a ALLOCCSTODSALIAS Not described in the SDK Allocates a new data selector that aliases an existing code selector ALLOCDSTOCSALIAS Accepts a data segment selector and returns a code segment selector that can be used to execute code in a data segment ALLOCSELECTOR Allocates a new selector ALLOCSELECTORARRAY Not described in the SDK Allocates an evenly spaced array of selectors CALLMSGEILTER Passes a message and other data to the current message filter function CATCH Copies the current execution environment to a buffer Complement is THROW CHANGESELECTOR Generates a temporary code selector that corresponds to a given data selector or a temporary data selector that corresponds to a given code selector Note that SDK 3 1 has renamed this PRESTOCHANGOSELECTOR both names will work DEATH Not documented in the SDK Turns off the Windows display driver and changes screen to text mode Used in Chapter 9 Complement is RESURRECTION
143. when creating the instance of the window All Windows messages are prefixed with WM_ such as WM_PAINT or WM COMMAND In my skeleton program I wanted to override default handling of WM_PAINT so I put paint wlpaint where wlpaint is my routine see above You will find the code for WM_PAINT handling is just about identical to that of Chapter 5 Ditto for WM COMMAND I put in my own routine called wlcommand because I wanted to respond to menu bar selections I also overrode WM_CREATE It that simple One thing you will notice with my routines wlcommand and wicreate is that I didnt put in PROC ENDP directives These are not essential and the routines work perfectly well without them Putting them in would make no difference In fact putting the PASCAL qualifier on would also make no difference since no parameters are being passed However notice that I did put PROC PASCAL ENDP around the wlpaint routine The reason for this is that I wanted to have LOCAL data and only TASM s high level PROC automatically takes care of LOCAL declarations The simple act of putting the PASCAL qualifier onto the PROC directive transforms it into a high level PROC Leave off PROC PASCAL ENDP if you wish but put it on if your routine has LOCAL data The only effect of the high level PROC will be to correctly handle LOCAL data within the procedure This is a syntactical deviation from the main discussion
144. will have new unique names The problem is that if you are writing an assembly language module that must access labels in C modules you cant reference them by name you can only reference them by their mangled names The only way to know the mangled names is by the stub method described above because the assembly language output will show all labels in their mangled form In Line Assembly A completely different approach is not to write the assembly language module as a separate tile but to write it in line with the C code You have to have a compiler that supports this and of those that do the in line assembler is not quite so fully featured as the stand alone assembler You lose in one way but gain in another What you gain is seamless integration with the C program You can write the assembly code with full access to the C labels and the registers that you use are automatically saved and restored by the compiler upon entry to and exit from your assembly module Here is a simple example WINDOW public active virtual int void TEXTOUT int void WINDOW TEXTOUT int x asm asm asm asm mov mov mov ENE si this dx si active addr relative to DS ah 2 21h Program Design 149 WINDOW windowl1 static object in data segment main 0 WINDOW windowl automatic object in stack seg windowl active 07 windowl TEXTOUT 0 _asm keyword I have shown here how the function
145. wndproc PASCAL si pop di pop si ret exportwndproc ENDP Having got the address of the object I then save the parameters that Windows passed to the callback into the object I then called wndprocQ whose address is actually in the object By default it is WINDOWwndproc shown below You can Program Design 167 override this to provide your own wndproc for a particular window such as a dialog box but in most cases you will leave well enough alone wndproc works fine for normal windows and has a very simple task it just implements a CASE statement to call the appropriate message handler These message handlers paint create timer etc are all pointed to via the object and can be overridden for any particular window Any WM_ message not catered to in the CASE statement results in a call to the default routine and Ive even provided for overriding this WINDOWwndproc PROC PASCAL now mov si now mov dx O mov cmp jne call cased cmp jne call Jm case cmp jne call Jmp case4 cmp jne Pa call casni cmp jne call Jmp case6 cmp jne call Jm case7 call endx ax si wmessage ax WM_CREATE case si create SHORT endx ax WM_DESTROY case3 si destroy SHORT endx ax WM_PAINT case4 si paint SHORT endx ax WM_ COMMAND case5 si command SHORT endx ax WM_LBUTTONDOWN case6 si lbuttondown SHORT endx ax WM_CHAR case7
146. word ptr cs instdata SIS_Instance_Data_Ptr iene 0 re A motes above code searches the environment block looking for fully specified path filename of this file then inserts this address es di into instdata Path of A point of clarification about the above code is needed A data the VxD structure has been filled in that Windows requires for loading the device driver We need to provide its path so the code looks into this TSRs PSP where the path filename is kept we can reuse the filename for the VxD since the TSR is embedded in the VxD Segment structure of TSR DOS Win Transitions 335 This code should be easy to read but do note that this TSR is EXE format which means that the PSP is a separate segment from the code segment I havent used the data segment For the SMALL model the code segment and PSP get loaded into memory contiguously that is the code immediately follows the PSP That is why to get the size of the PSP I merely subtracted ES from CS as ES initially points to the PSP segment next problem is we need to force WINAPP our windows application to load Initialise length of ID string mov WORD PTR cs My_ID_ Block OFFSET My _Name_End Setting up the WinApp data structure OFFSET My Name The following code which is another data structure required for launching the Windows application continues from above mov WORD PTR cs TSR_Info TSR_Exec_Cmd mov WORD
147. you so now is the time to be clear on what they are Hexadecimal numbers are base 16 i e are based upon a number system with 16 digits rather than the 10 in decimal or the 2 in binary They are Decimal 0 1 2 3 Binary CPU Architecture 9 4 5 6 7 8 9 A B Cc D E F 4 5 6 7 8 9 10 11 12 13 14 15 0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111 SS eee x86 CPU initialisation Registers 20 bit address Major components ofa PC The first row shows hex digits followed by decimal then binary note that hex numbers are just a shorthand notation for binary which is why they re used Each hex digit represents 4 binary bits and FFFFO hex is the same as 1111 1111 1111 1111 0000 binary Note that hex is not quite the same as BCD as described above Registers and Memory We haven t finished covering the really basic stuff When powering up the PC you are also powering up the 8088 8086 80286 80386 80486 or Pentium CPU whichever your particular computer has The CPU has internal registers that are initialised to certain values at power up Two of them the Code Segment CS register and the Jnstruction Pointer IP are initialised in a very special way Hey before we go on about registers just what are they Figure 1 3 introduces the registers of the PC but do note that registers can be in any integrated circuit such as the video adaptor card To return to the Code Segme
148. 0 the operating system kernel and device drivers run at the most privileged level 0 while Windows applications and DLLs run at level 1 DOS applications being the least trusted run at level 3 However Microsoft changed its mind with Windows 3 1 and moved Windows applications and DLLs down to level 3 also This includes all the DLLs of the Windows API When I upgraded from Windows 3 0 to 3 1 I had the distinct but subjective feeling that the new version was a tad slower The changes in privilege could be the reason Of course Microsoft claimed just the opposite that the new version was faster which could have been true taking into account the new 32 bit file and disk access which I originally had turned off Then when I upgraded to Windows for Workgroups 3 11 I again had the subjective feeling that everything had slowed down I have never tried to quantify this Version 3 11 seemed to take longer to load which may have had something to do with the fact that when going from 3 1 to 3 11 I decided to network two PCs Then when I upgraded to Windows 95 Anyway the current situation with Windows is that applications run at level 3 least privileged Unfortunately this seriously 287 288 Windows Assembly Language amp Systems Programming Device driver Reference source hampers my style if I want to do my own I O If my requirement is direct access to memory and I O ports or interrupt handling invariably th
149. 11b clear dpl field mov es bx 5 al mov al es bx 6 get granularity amp seg size bits or al 01000000b sset bit7 for 32 bit mov es bx 6 al or bx 0100b set bit 2 selects ldt leave dpl 0 mov di bx temp save mov descriptor_selector bx jsave create callgate to above descriptor push es invoke ALLOCSELECTOR O create a descriptor in ldt pop es cmp ax 0 je selectorerror mov ringQ_cs ax save final selector and ax 0OFFF8h get offset of descriptor in ldt mov bx ax mov es bx ringOfunc my ring0 code declared EXTRN mov es bx 2 di ringO alias mov BYTE PTR es bx 4 0 dwords copied to stack mov BYTE PTR es bx 5 11101100b present 1 dpl 3 app 00 type mov WORD PTR es bx 6 0 C 386 callgate qwert jmp SHORT qwerty lockfailed extensionsnotfnd selectorerror lea si ring0errormsg call errormsgproc call xquitmessage quit program qwerty ret makering0selector ENDP i freeourselectors PROC invoke FREESELECTOR descriptor_selector invoke FREESELECTOR ringO_cs invoke GLOBALPAGEUNLOCK cs ret freeourselectors ENDP INT 2Fh The first thing that makeringOselector does is lock the segment in function memory as the ring O0 descriptor and call gate that are about to be 168Ah created will have their present bit set indicating that they are in physical memory The next problem is where is the LDT The exact location of the LDT is not something that a ring 3 pro
150. 235 The Windows library file supplied by your software vendor such as LIBW LIB Microsoft or IMPORT LIB Borland provide your program with access to the DLL functions Whether or not you can access REPAINTSCREEN directly from your program is determined by the inclusion of the linkage information in these link files You will find that later versions may provide the linkage even to undocumented functions however I have shown how to do it the hard way here in case you have to do it for any functions including those in other DLLs 232 Windows Assembly Language amp Systems Programming REPAINTSCREEN redraws the screen and is redundant here actually INT 2Fh AX 4002h restores VDD Windows access to the display driver and also causes the screen to be redrawn REPAINTSCREEN is required after RESURRECTION Change Video Mode BIOS So in between having saved the screen and cleaning up prior to INT 10h going back to Windows how do you change the video mode If you are familiar with DOS and BIOS INTs youll know it is INT 10h well it still is Since an INT causes the CPU to look in the IDT Interrupt Descriptor Table for the location of the routine and not in the old IVT Interrupt Vector Table see pages 33 any of the routines can be replaced as required or the CPU redirected to the Real mode routine with appropriate translations Thus INT 10h stills works even though it is called from a Protected mod
151. 31h returns ax push ax POP es mov ax hwnd mov es hwndcs ax save handle of window in code seg mov ax es mov es dsselector ax save data alias in code could put some code for hooking the IDT hookreal Pop ds restore it again 0k now to hook Real mode in hook 60 mov ax 0200h get Real mode vector mov bl 60h int 31h j gt cx dx seg off mov es cs dsselector mov es offsetrealint dx save old vect mov esS segmentrealint cx now must reflect the Real mode int up to prot mode code push ds save mov es cs dsselector get alias Addr of buffer in es di mov di OFFSET callbackbuffer 284 Windows Assembly Language amp Systems Programming mov ax 0303h alloc Real mode callback push cs pop ds addr of prot code mov si OFFSET runtime2 int 31h gt CX dx seg off pop ds restore snow hook the ivt mov ax 0201h set Real mode vector mov bl 60h shook int in ivt int 31h getout pop es popa ret Real mode The data structure referred to as callbackbuf f er is the same register callback structure used to pass register values between Real and structure Protected modes as discussed on page 269 where function 0300h is introduced this is for calling a Real mode interrupt from Protected mode which is going the other way WinApp Actually the piece of the puzzle consisting of the WinApp code ISR is in two parts the install portion above and a run time portion The latter
152. 606h are available in Windows Standard mode Note also that these services although designed for communication between device drivers are quite general and can be used by any program Chapters 11 and 14 develop a TSR that uses them e AX 1600h Obtains the version number of 386 Enhanced mode Windows e AX 1605h Windows calls this to tell DOS drivers that it is loading example of usage Chapter 14 e AX 1606h Windows calls this to tell DOS drivers that it is quitting example of usage Chapter 14 e AX 1607h A virtual driver calls a DOS driver e AX 1608h Windows calls this to tell DOS drivers that it has completed initialisation e AX 1609h Windows calls this to tell DOS drivers it is exiting Enhanced mode e AX 1680h Yields the current virtual machine time slice e AX 1681h A driver calls this to tell Windows not to switch virtual machines e AX 1682h This is the complement of 1681h e AX 1683h Returns the ID of the currently executing virtual machine INT 4Bh DMA services Overview Low eve function Summary BIOS DOS Windows Services 207 e AX 1684h Allows a DOS mode driver to request services from a virtual driver e AX 1685h Allows a driver to switch virtual machines examples of usage Chapters 11 and 12 Windows drivers also make use of INT 4Bh for virtual Direct Memory Access DMA and I refer you to page 264 Again these are extensions that are not part of DOS but
153. ASM version 5 is in Chapter 13 Skeleton Analysis WINHULLO ASM gt WINHULLO EXE Windows demo MODEL SMALL Program fisting The MODEL directive is an instruction to the continues until page assembler If you leave it off the program will still 17 assemble ok It tells the assembler how many data Th p and code segments this program will need and gives Lip ale de KORSI Standard names and qualifiers to the segments MO DEL T ave specified SMALL which means that the program will have one code segment and one segment with combined data and stack You have a choice of TINY SMALL MEDIUM COMPACT and HUGE your assembler manual will have details on each of these See page 119 for more information 112 Windows Assembly Language amp Systems Programming If your assembly program has to be linked with a high level program you would normally choose the same model that was used for compiling the high level code This ensures smooth linking INCLUDEWINDOWS INC l a IDM_QUIT EQU 200 menu identifiers must be IDM_ABOUT EQU 201 same as defined RC file WINDOWS Here is where WINDOWS INC is inserted If you look back to INC page 94 you will see that I have still left in the above two equates These come from the RC file see page 89 If there were enough of these I would have put them into their own INC file and included it in both WINASMI ASM and WINASM1 RC Unlike C external functions must be explicitly declared in
154. CPU will always know where the GDT is So what purpose does the GDT perform One major use is to hold the base addresses of all the LDTs Whenever the operating system creates a new task it also creates an LDT for that task and makes a new entry in the GDT This entry has the address of the LDT Bear in mind that I m generalising here Windows 3 x and 95 use one LDT for all Windows applications and separate LDTs for each DOS application while NT is different again Seem complicated It is which is why I m generalising for now The GDT has the base addresses of the LDTs but which one is currently executing For this the CPU has the LDT register which is just an index into the GDT pointing to the current LDT descriptor Let me use the term descriptor from now on Each entry in a GDT or LDT is called a descriptor So let s suppose the CPU wants to fetch the next instruction of whatever task is currently executing The CPU will already know where the current LDT is because it already would have read the GDT entry as indexed by the LDT register Shadow Registers Incidentally a most important element is shadow registers Look back to the picture of the CPU registers in Figure 1 11 page 24 and you will see that some of them have shadow registers So does the LDT register These shadow registers hold the actual addresses or more correctly the descriptors read from the table When the CPU reads the GDT and gets the desc
155. CTIONO mov ah 00 will change back to graphics mov al winvideomode mode and restore Windows int 10h display driver mov ax 4002h call RESURRECTION PASCAL int 2Fh pndes07 0 0 0 0 0 Faas call RELEASEDC PASCAL hwnd call lprepaintscreen hdc PASCAL Thanks to Undocumented Windows ana for showing me how many params nodpmi to feed RESURRECTIONO nomodule ret directvideo ENDP Calling a function a DLL There are a host of things I can say about this routine I have itemized major points below Call REPAINTSCREEN I mentioned earlier that I have used REPAINTSCREEN as an example to show how to get at a DLL function at run time which is one option if linkage information is not provided in the library file The standard technique is to call GETMODULEHANDLE Q to get a handle for USER EXE a file is a module in Windows parlance but the file name can be different from the module name then call GETPROCADDRESSO to get the FAR address of the function within that module If you would like to see another example of accessing a function in this way Microsofts Programmer s Reference Volume 2 Functions provided with the SDK 3 1 and available separately gives an example of LOADLIBRARY instead of GETMODULEHANDLE GETPROCADDRESSQ and FREELIBRARYQ to access a function in TOOLHELP DLL Thity two bit applications are somewhat more constrained see notes on page 235 EXE header extraction utilit
156. Chapter 1 and consolidate with further study if required CMP instruction Basic Assembly Language 5 The CMP instruction has already been introduced but involves arithmetic comparisons so it will be considered again here The example below subtracts 127 from AL and the result sets the appropriate flags Decimal is the default with an assembler unless an h is appended to designate hex DEBUG can only have hex We will treat 127 as being decimal in this case cmp al 127 hypothetical subtract 2S complement versus unsigned Unsigned 2 s compl Unsigned 2 s compl The CMP instruction can be followed by a conditional jump that jumps or doesn t jump depending upon the flags Although CMP subtracts the two values it is only done hypothetically and the two operands are left unchanged CMP doesn t care whether the number is unsigned or 2 s complement it just subtracts them It is the same for all the addition subtraction arithmetic instructions it is up to the programmer to decide how to treat the operands and the result This point can be clarified Since the above example is dealing with S bit operands the range of values depends upon whether we are treating them as 2 s complement or unsigned number O lt gt 255 or 00 lt gt FF in Hex 128 lt gt 127 Oor 80 lt gt 7F in Hex So if AL 128 the example CMP instruction will give a hypothetical result of 128 127 1
157. Controls can be all sorts of things including edit boxes check boxes buttons and scrollbars 172 Windows Assembly Language amp Systems Programming Control class Complete 00 program with a control Figure 6 2 Simple 00 demonstration program ee Message Box Se A Donne Y a2 OO oe RIEIRO o Created by Barry Kauler 1992 K RN KK LN ae o OR 5 LOSE See o CRA Xo S gt gt Since a control is just a window why not use the WINDOW structure and make Well yes it can be done except that controls do have some special requirements If you think in terms of conventional programming you would probably delve into make and see how to patch in the handling of such a special case Unfortunately this is one of the major problems with such programming the continual patching of code to handle special cases If your code works the process of patching is liable to make it less stable and predictable Better to leave well enough alone We have a functional make for normal windows so lets think like 00 programmers We could simply create another instance of WINDOW say window2 and override the make with a new routine That is ok if all we ever want to do is create one control but it is nicer if we think in the long term Why not create another class call it CONTROL and let it inherit everything from WINDOW but with any necessary overrides This is what has been done with my program and the
158. D is not a bottleneck itself from the point of view of memory management as some books will have you believe I discuss this issue on page 324 Perhaps I am getting ahead of myself since I haven t even discussed the service routine itself The above points do tie in with the service routine however We may want to store writable data in the code segment of the ISR which will cause problems Also hardware interrupts are a special case In practise you may have to do more than just specify FIXED I have gone into this in more detail on page 323 Also some relevant Windows functions GLOBALHANDLE GLOBALFIX and GLOBALPAGELOCK were introduced on page 2 10 While I m referring you all over the place for extra information I might as well do it some more The above install routine works for hardware or software interrupts that is any entries in the IDT or IVT if the CPU is running in Real mode There are DPMI equivalents see the Appendices What about exceptions These have to be treated as a special case see page 258 Service Routine ISR No an ISR doesn t have to be a DLL or some other separate program It can simply be a procedure in the same program that has the install code It will not be called from the program however There is a problem with addressing data upon entry to the service routine because DS will be an unknown value Look back to page 33 for a review of the steps that the CPU goes through upon an int
159. DEL is MODEL memorymodel language modifier language Global labels The language modifier is WINDOWS ODDNEAR FARNEAR or NORMAL The exact syntax may vary with some assemblers I got this information from the Borland TASM version 2 5 manual Special notes on Microsoft MASM compatibility are on page 125 We would not normally put the WINDOWS language modifier in because WINMAIN doesnt need it However if you were writing callback functions only in assembly language and perhaps the WINMAIN in a high level language then yes put it in This note only applies to 16 bit TASM applications Private and Global Data Traditional assembly language people are accustomed to all labels being global but with the high level procedures this is not necessarily the case Any procedure that uses a language qualifier such as PASCAL automatically has private labels at least that is the case with recent versions of MASM let us treat MASM as the reference standard All data and code labels declared inside the procedure are private to that procedure and are unrecognized outside it which means of course that you can use the same labels elsewhere High level procedures are declared either explicitly by putting a language qualifier into the PROC declaration or implicitly in the MODEL declaration Do note that the defaults set by MODEL can be overriden in individual PROCs and CALLs as required So what labels are global Thos
160. DOW FAR SHOWWINDOW FAR EXTRN GETMESSAGE FAR EXTRN LOADCURSOR FAR TRANSLATEMESSAGE FAR Program Design 163 EXTRN DISPATCHMESSAGE FAR LOADICON FAR EXTRN TEXTOUT FAR EXTRN MESSAGEBOX FAR GETDC FAR EXTRN RELEASEDC FAR EXTRN SELECTOBJECT FAR GETWINDOWWORD FAR EXTRN SETWINDOWWORD FAR SENDMESSAGE FAR EXTRN DESTROYWINDOW FAR DATA MAIN TABLE VIRTUAL initinstance WORD kickstart VIRTUAL hinstance WORD 0 VIRTUAL hprevinstance WORD 0 VIRTUAL ncemdshow WORD 0 WINDOW TABLE VIRTUAL defiinewndclass WORD WINDOWdefinewndclass VIRTUAL create WORD WINDOWcreate VIRTUAL paint WORD WINDOWpaint VIRTUAL command WORD WINDOWcommand VIRTUAL timer WORD WINDOWtimer VIRTUAL resize WORD WINDOWresize VIRTUAL mousemove WORD WINDOWmousemove VIRTUAL lbuttondown WORD WINDOW1lbuttondown VIRTUAL lbuttonup WORD WINDOW1buttonup VIRTUAL Char WORD WINDOWchar VIRTUAL defaultproc WORD WINDOWdefaultproc VIRTUAL destroy WORD WINDOWdestroy VIRTUAL make WORD WINDOWmake VIRTUAL wndproc WORD WINDOWwndproc VIRTUAL hwnd WORD 0 VIRTUAL wmessage WORD 0 VIRTUAL wparam WORD f VIRTUAL lparam DWORD VIRTUAL classstyle WORD CS VREDRAW CS _HREDRAW VIRTUAL sziconname BYTE 3 VIRTUAL szcursorname aunt 32 i VIRTUAL hbrbackground WORD COLOR_BACKGROUND VIRTUAL szclassname BYTE 32 0 VIRTUAL sztitlename BYTE 32 0 VIRTUAL hmenu WORD 0 VIRTUAL hwndparent WORD 0 VIRTUAL wheight WORD 200 V
161. DPMI translation function to simulate a Real mode FAR call e AH 44h subfunctions 02h 03h 04h and 05h These I O control IOCTL subfunctions are used to receive data from a device or send data to a device Since it is not possible to break the transfers automatically into small pieces the caller should assume that a transfer of greater than 4K will fail unless the address of the buffer is in the low 1 megabyte AH 44h subfunction 0Ch Only the minor function codes 45h Get Iteration Count and 65h Set Iteration Count are supported from Protected mode The extensions of this IOCTL subfunction that are used for code page switching minor function codes 4Ah 4Ch 4Dh 6Ah and 6Bh are not supported for Protected mode programs You must use the DPMI translation functions if you need to use this IOCTL subfunction to switch code pages e AH 65h Get extended country information This function is supported for Protected mode programs However all the DWORD parameters returned will contain Real mode addresses This means that the case conversion procedure address and all the pointers to tables will contain Real mode segment offset addresses You must use the DPMI translation functions to call the case conversion procedure in Real mode This is a direct quotation from the Developer s Notes The term Real mode in this publication is also taken to cover virtual 86 mode 202 Windows Assembly Language a
162. EAR jump as the destination is usually in the same segment jmp PLACE1 PLACE mov ax 0 NEAR JMP code label arbitrary instruction At this point it is instructive to consider how the assembler will assemble this JMP instruction into memory Obviously it has to be converted to machine language or binary bits That is what any compiler or assembler does Figure 2 3 Generation of machine code NEAR jump Increasing Operation code addresses Operand low downward Operand high In Figure 2 3 you can see the basic scenario The first one or sometimes two memory location s contain the instruction code or operation code often referred to as the op code that identifies this as a JMP instruction or whatever while the following zero or more bytes are the operand In the case of the NEAR jump instruction the operand contains a 16 bit offset which is the place to jump to But and this is most important the addressing structure of all the Intel x86 CPUs uses FAR JMP SHORT JMP Range of a SHORT jump Basic Assembly Language 43 byte addressing meaning that each address addresses a one byte 8 bit memory location Therefore the operand requires two memory locations as shown in Figure 2 3 as operand low and operand high The Intel x86 convention is that the low half of the value is stored at the lower address It is also useful to note that if the IMP is a FAR jump that is to another code segm
163. Figure 1 4 You know the 640K RAM specification given for the PC this RAM exists in the memory map from address 00000 up to the 640K shown in Figure 1 4 You can see that the first 140K or thereabouts is occupied by various things which leaves about 500K free for user programs Of course this free memory is a very variable thing depending on a number of factors For example if the CONFIG SYS file specified some device drivers they would be loaded into memory and kept there If DOS is to run COMMAND COM will have to load and for Windows it will be WIN COM Same for any resident pop up programs such as Sidekick though it is rare that anyone uses these today All of these will reduce your free memory Figure 1 4 is simplified and in practise there will be a lot more functions occupying the memory space Do be clear on one thing not all of the address space is necessarily occupied The address range from 00000h down to 9FFFFh 640K is occupied by contiguous RAM and the region marked as free RAM is available for a program to load into from disk At the end of the 1M region is the BIOS ROM and maybe other ROMs before it Basically ROM and RAM in this middle region are provided by plug in expansion cards Examples of video and hard drive cards are shown though the addresses are in some cases adjustable It is useful to note at this point that during the power on sequence the region C0000h to F4000h is scanned to see if an
164. First I only want this ISR to work when Windows is loaded so test winloaded flag cmp cs winloaded 0 note cs override since ds not set jne firsthurdle chain jmp DWORD PTR cs oldoffivt9 chain to old int 9 firsthurdle cmp CS isrbusy 0 jne chain mov c cs isrbusy 1 jprevent reentrance secondhurdle j we re in but call old int 9 first which will take care FOT EOL ere pushf call DWORD PTR cs oldoffivt9 now setup registers push es save working registers push ds pusha push cs set ds CS pop ds Code to co exist and synchronise with DOS if you want z to call DOS INT 2lh functions only allowed above ODh Pack test the inDOS flag wise to switch to a local stack change to PSP of TSR save break setting and turn off redirect INT s 1Bh 23h and 24h save extended error checking whew DOS Win Transitions 327 sti EOI already achieved by call to old vector next hurdle is to find out if Windows is in Standard or Enhanced mode One way is to test INT 60 to see if it is hooked if not then we must be in Enhanced mode as WinApp only hooks IVT in system VM However all we will do is test winmode flag mov al winmode and al 1 jz Enhanced bit 0O 0 if Enhanced Standard jmp SHORT exit4 Enhanced I will be a little bit fussy here In theory this ISR could be entered when the CPU is in the system VM hence we will not want to do the transfer from another
165. INDOW doesnt look much like that for structures see page 65 but dont worry about that for now There is a tick here I have taken all the red tape the complexity of the Windows program and hidden it away in the Include file WINASMOO INC This hiding of the unnecessary complexity and exposing only what is needed can only be done by using 00 techniques My object oriented Include file is a world first Nobody has done this before No Microsoft or Borland documentation will tell you how to do this The Microsoft documentation is appalling from the assembly language programmer viewpoint The Borland manuals keep getting thinner too Mind you the simple program you see above didnt just materialize in my mind I just about tore my hair out at times I came across a very interesting article by John Dimm titled A Tiny Windows Class Library in Programmers Journal USA Dec 1991 I also studied Norton and Yao Borland C Programming for Windows Borland Bantam USA 1992 A few ideas come from these and other sources but I ended up doing my own thing and what is presented in this chapter is quite simple and elegant It is written in Borland TASM version 3 0 for the simple reason that this assembler is specifically designed for OOP However I must emphasize that the code is very general and with some modification will work with earlier versions of TASM and with MASM I have pointed out the divergence from non OOP assemb
166. IRTUAL wwidth WORD 250 VIRTUAL y_coord WORD 0 VIRTUAL x coord WORD VIRTUAL createstylelo WORD VIRTUAL crea estylehi WORD WS OVERLAPPEDWINDOW VIRTUAL hfornt WORD mainl MAIN j create static instance pwindow DW 0 ptr to current window object pwindowflag DB 0 O pwindow not valid e oop o o s aue oo o o o o o o o o o o l o G M G M M M M M M M I i gG G l i i M i G G G M a lH H 164 Windows Assembly Language amp Systems Programming Cr PUBLIC WINMAIN WINMAINPROC PASCAL NEAR hInstance WORD hPrevinstance WORD lpCmdLine DWORD nCmdShow WORD LOCAL msg MSGSTRUCT see WINDOWS INC Notice the use of the prefix This keeps these labels unique to this procedure Refer back to page 2 1 lea si mainl mov ax hinstance save params in mainl object mov si hinstance ax It should make sense so far In the data segment I defined two structures MAIN and WINDOW There will only be one instance of MAIN in the application called main1 see above The application is entered from Windows at WinMain and I have used main1 to save the parameters This is what is happening now mov ax hprevinstance i mov si hprevinstance ax mov ax ncmdshow mov si ncmdshow ax call si initinstance call kickstart no pascal or ax ax jne messageloop ret You should be able
167. In a nutshell LabView is an environment in which you can very rapidly develop applications with a single line of coding LabView applications can be recompiled unchanged to run on Macintosh PC with Windows Windows NT and Sun workstations with more to come The speed with which you can put programs together has to be seen to be believed and phenomenal productivity improvements 360 Windows Assembly Language amp Systems Programming Dataflow visual programming Speed amp size are well documented But enough of that I am not a salesperson for National Instruments nor is this book about LabView programming So Ill give you all sides of the picture and get onto how I see assembly language fitting in LabView is based upon a dataflow model but there are enough control flow mechanisms built in to get around the limitations of the pure dataflow concept Dataflow means that you construct programs by drawing data paths between icons on the screen and execution follows the data paths Figure 15 3 shows this Look at the diagram at the bottom of the figure and you will see how icons have been interconnected to form the program or diagram Control structures are also shown such as a while loop and a case structure Note that the case structure is very efficient in its use of screen real estate cases are superimposed like a deck of cards with a simple selection box on top for flicking through them This leads to
168. Input One thing to bear in mind is that although Windows 3 x is non preemptive the device drivers are still working asynchronously as indeed is the case in Windows 95 Key presses and mouse activity can still generate messages which will be placed into your application queue So your program may have saved the Windows video state and gone to mode 7 or whatever and done its thing When finished and after the clean up of restoring the video state and maybe calling REPAINTSCREEN your program would normally continue on in the normal fashion if execution is within a callback control will continue on and return to Windows and a message waiting in the queue will then be sent to the message loop in WinMain If perchance you dont want to respond to messages received during the direct video period you can use PEEKMESSAGE to see what is there and discard it Note that PEEKMESSAGE can be used at any time within your callback to interrogate the queue It gives you the options of checking the queue with or without removing messages checking for a range of messages only and of not yielding to Windows The main advantage of PEEKMESSAGE is that it doesnt wait if there are no messages on the queue it returns immediately great for getting keyboard or mouse input in a non event driven manner a bit like old times The next advantage is that if you are doing some kind of direct access and dont want any other applicati
169. LASSFIRST Retrieves information about the first class in the class list e CLASSNEXT Retrieves information about the next class in the class list e GLOBALENTRYHANDLE Retrieves information about a global memory object e GLOBALENTRYMODULE Retrieves information about a specific memory object e GLOBALFIRST Retrieves information about the first global memory object e GLOBALHANDLETOSEL Converts a global handle to a selector e GLOBALINFO Retrieves information about the global heap e GLOBALNEXT Retrieves information about the next global memory object e INTERRUPTREGISTER Installs a function to handle system interrupts e INTEBBUPTUNBEGISTER Removes the function that processes system interrupts LOCALFIRST Retrieves information about the first local memory object e LOCALINFO Fills a structure with information about the local heap e LOCALNEXT Retrieves information about the next local memory object e MEMMANINFO Retrieves information about the memory manager 214 Windows Assembly Language amp Systems Programming e MEMORYREAD Reads memory from an arbitrary global heap object e MEMORYWRITE Writes memory to an arbitrary global heap object e MODULEFINDHANDLE Retrieves information about a module e MODULEFINDNAME Retrieves information about a module e MODULEFIRST Retrieves information about the first module e MODULENEXT Retrieves information about the next module e NOTIFYREGISTER Installs a notification c
170. LS With DEBUG any instruction that transfers control to another address must contain the actual offset What is What is DEBUG It is a program that comes with DOS and from DEBUG the DOS prompt you will only have to type the name of the program to execute it DDEBUG EXE is a way of becoming familiar with the instruction set it allows you to try out the instructions and put together simple programs These examples show that DEBUG must have an actual address not labels MOV CX 9 PLACE1 this is at 113 say MOV AX 0 arbitrary instr LOOP 113 absolute offset no label 42 Windows Assembly Language amp Systems Programming LOOP PLACE1 using a label JMP instruction SHORT NEAR and FAR However by writing the code in proper assembly language we do not need to know actual addresses The second example here shows how a proper assembler can have a symbolic address marker in this case PLACE In Figure 2 2 we looked at a CALL instruction but there is also a JMP jump instruction that transfers execution to the address specified in its operand in the same manner as the CALL instruction but with a major difference no return address is saved on the stack This is because JMP is used when you do not want execution to come back It was also explained above that the CALL can be NEAR or FAR but the JMP can be SHORT NEAR or FAR The example code below shows a JMP to a label Usually an assembler defaults to a N
171. M_ABOUT Is About selected jne notabout call MESSAGEBOX PASCAL si hwnd cs OFFSET szmsg cs OFFSET szhdg MB OK notabout ret notmenu cmp si wparam IDOK button child window selected snote that lo word of lparam has handle of control window hi word of lparam has notification code jne notbutton lea si controll since si points to windowl call DESTROYWINDOW PASCAL si hwnd kill button mov si hwnd O must clr hwnd if want to makeO later notbutton 174 Windows Assembly Language amp Systems Programming ret szmsg DB Created by Barry Kauler 1992 0 szhdg DB Message Box 0 wichar let s bring back the button if any key pressed lea si controll since si points to windowl call si make PASCAL si ret er ra IDOK equates to 1 and is defined in WINDOWS INC It isa convenient identifierto pass to the parent callback in the wparam of the WM_COMMAND message Pressing the button results in this message Make for CONTROL class Now for the new make routine Here are extensions for handling controls DATA _ CONTROLTABLE WINDOW VIRTUAL make WORD CONTROLmake peewee we ee ee CODE CONTROLmake PROC PASCAL now mov si now xor ax ax clear ax default return value does this window already exist check hwnd cmp si hwnd O jnz ending Is it a child all controls are child windows cmp Si hwndparent 0 jne nending so we have to give it one this involves an masupa io
172. Matt is actually quoting from his book Windows 95 Systems Programming Secrets IDG Books USA 1995 In Unauthorized Windows 9 5 Andrew Schulman made extensive use of undocumented functions in KERNEL32 DLL Although there obviously werent header files for these functions the functions appeared in the import library for KERNEL32 DLL Calling these functions was as simple as providing a prototype and linking with KERNEL32 LIB In subsequent builds of Windows 95 after Andrew s book came out these functions disappeared from the import library for KERNEL32 DLL Surprise Surprise At the same time these function names disappeared from the exported names of KERNEL32 DLL These undocumented functions were still exported however The difference is that they were exported by ordinal only IDG Books USA 1994 236 Windows Assembly Language amp Systems Programming RESURREC TION Video mode 7 Now normally this would have been only a small nuisance to work around You should be able to simply call GetProcAddress and pass in the desired function ordinal as the function name O in the HIWORD the ordinal in the LOWORD and get back the address In a normal sane world this would work However at some point during the beta Microsoft added code to GetProcAddress to see if its being called with the ordinal form of the function If so and if the HMODULE passed to GetProcAddress is that of KERNEL32 DLL GetProcAddress fa
173. NT declaration above will cause them to be combined What I think is stupid is that I have to resort to the old fashioned SEGMENT directives to achieve this Anyway note that I gave the ring O segment a different name _TEXT2 but the choice is arbitrary The qualifier USE32 defines the segment as 32 bit which means that the assembler will assemble 32 bit instructions without the prefix and 16 bit instructions with the prefix The P on the end of 386P permits use of the ring O restricted instruction set that is the assembler will assemble them 300 Windows Assembly Language amp Systems Programming What you can do in ring 0 Fixing code amp data at known linear addresses Finally you can put a number after RETF to indicate the number of bytes to pop off the stack Use this to remove parameters passed by the call gate if calling in conformance with the Pascal convention So what can we do in this 32 bit ring O0 procedure FLAT Memory You will find the program discussed so far on the Companion Disk in directory ASMRINGO This chapter also describes an enhancement to this program that is contained in FLATASMO ASMRINGO EXE as described so far demonstrates how a 16 bit ring 3 program can make the transition to a 32 bit ring O code segment and come back Once in ring 0 you can execute OUT IN CLI STI etc without intervention by the CPU You can also use the privileged instructions of the 386 that al
174. NT 1 Ch INT 20h INT 2 1h INT 21h AH 25h 35h INT 2 1 h AH 38h INT 2 1 h AH 44h INT 2 1 h AH 65h INT 25h INT 26h INT 27h INT 28h Index 415 20 201 304 33 200 200 252 201 201 201 200 200 200 200 The INT 2Fh extensions provided by DPMI are described in Appendix C Other extensions are described in Appendix D Where further described in the book see below NT 2Fh extensions INT 2Fh AX 1600h NT 2Fh AX 1605h NT 2Fh AX 1606h INT 2Fh AX 1607h INT 2Fh AX 1608h NT 2Fh AX 1609h NT 2Fh AX 160Bh NT 2Fh AX 1680h NT 2Fh AX 168 1 h NT 2Fh AX 1682h INT 2Fh AX 1683h NT 2Fh AX 1684h NT 2Fh AX 1685h NT 2Fh AX 1686h NT 2Fh AX 1687h INT 2Fh AX 168Ah NT 2Fh AX 4000h NT 2Fh AX 400 1 h NT 2Fh AX 4002h NT 2Fh AX 4003h NT 2Fh AX 4004h NT 2Fh AX 4005h NT 2Fh AX 4006h 205 206 348 206 328 338 206 328 338 206 206 338 206 338 204 206 349 206 349 206 349 206 327 206 349 206 327 204 204 338 204 297 205 205 229 205 229 205 205 205 230 205 230 416 Windows Assembly Language amp Systems Programming INT 2Fh AX 4007h 205 230 The INT 31h functions provided by the DPMI host are described in Appendix C Where further described in the book see below INT 3 1 h functions 203 INT 3 1 h AX 0002h 228 269 INT 3 1 h AX 0200h 269 INT 3 1 h AX 0300h 269 INT 3 1h AX 0303h 279 INT 4Bh DMA services 265 INT 50h to 57h 258 Interfacing with C 147 Interrupt Controlle
175. None FPATAN Partial arctangent UE PE FPREM Partial remainder IE DE UE FPREM1 Partial remainder IEEE FPTAN Partial tangent IE PE FRNDINT Round to integer IE PE FRSTOR source Restore saved state None FSAVE FNSAVE dest Save state None FSCALE Scale IE OE UE FSETPM Enter Protected mode None FSIN Sine FSINCOS Sine amp cosine FSORT Square root IE DE PE FST dest Store real TE OE UE PE FSTCW FNSTCW dest Store control word None FSTENV FNSTENV dest Store environment None FSTP dest Store real amp pop IE OE UE PE FSTSW FNSTSW dest Store status word None FSUB dest source Subtract real IE DE OE UE PE FSUBP dest source Subtract real amp pop IE DE OE UE PE FSUBR dest source Subtract real reversed IE DE OE UE PE FSUBRP dest source Subtract real reversed amp pop IE DE OE UE PE ge FTST Test stack top against 0 00 IE DE FUCOM Unordered compare FUCOMP Unordered compare amp pop FUCOMPP Unordered comp amp pop twice Instruction Summary 3 77 FWAIT Wait while 8087 is busy None FXAM Examine stack top None FXCH dest Exchange registers IE FXTRACT a Extract exponent amp Significand IE se FYL2X ST 1 log ST 0 PE FYL2XP1 ST 1 log ST 0 1 PE Keyboard Tables Virtual Keys VK_LBUTTON Left mouse button VK_RBUTTON 12 Right mouse butto
176. OC jmp return Back to Windows Case The above code determines the type of message and jumps to an Statement appropriate routine If the message is not to be handled explicitly by the callback it falls through to DEFWINDOWPROC for default handling WM_ CREATE Follow through the case of WM_CREATE The earlier case logic message will bring execution to create where I have obtained the handle to a font WM_CREATE is sent by Windows when the window is created in response to CREATEWINDOW and for a simple skeleton you do not really need to do anything with this message just send it on to DEFWINDOWPROC Note that even fonts have handles and to use the OEM font in the program this is a convenient time to get its handle NL create mov ax OEM_FIXED FONT push ax call GETSTOCKOBJECT mov hoemFont ax handle to font jmp SHORT break e ee eH Fw ee sub ax ax The Bare Bones IOS push ax call POSTQUITMESSAGE jmp SHORT break WM_CHAR 1 implemented the WM_CHAR case to show how to respond to a message keyboard character See the keyboard tables in Appendix B Refer to a Windows programming book on the difference between ANSI and ASCII char I haven t bothered to respond to key presses in any way in this simple skeleton gt jmp SHORT break WM_PAINT Even the most basic skeleton will need the following code in message response to WM_PAINT You will need to put in BeginPaint
177. OS DOS services is that the cursor and text I O services treat row and column just like text mode even if the screen is in graphics mode The number of rows and columns for each graphics mode can be found from a table such as in Thorn Hogas PC Sourcebook see page 82 1 used INT 10h to obtain the current mode and number of columns but do read DPMIO README TXT for special information on Super VGA hosting Direct Hardware Access 243 Before you run this program change Windows to standard VGA 640 x 480 x 16 that is 16 colors and restart Windows Yes it works on Windows 95 The not entirely appropriately named dpmidemo is called every 200ms which is how the window always manages to stay on top You can see that I called SETTIMER to create a Windows software timer and note also that I killed it before exiting the program The reason for this is that Windows timers are a limited resource Figure 9 1 shows the result of this program on screen Figure 9 1 BIOS DOS O P to screen deip 4 AmiPi Print Manager Clipboard J bject BE Aa SS Its a bit like trying to mix water and oil If you try the program one feature that you will observe is that ghosting can occur in windows moved underneath so an improvement would be to hook all WM_MOVE messages and append a WM_PAINT message The problem is that whenever you move drag a window on the screen Windows simply performs a shift of the window image a
178. Opening Windows 83 Physical region handle HSTR String resource handle LOCALHANDLE Local memory handle HWND Handle of a window One thing that you will notice throughout much of this book is my disregard for upper or lowercase For example I have usually used uppercase for function names This stems from the dynamic link libraries themselves in which the functions are recorded exported in upper case Mixed case in the case of Windows functions is for readability only Another factor is that the assembler treats upper and lowercase alike well that can usually be controlled by a switch I did have a change of heart in the matter of case sensitivity and you will find the 32 bit application in Chapter 13 has correct case on everything The link step also can be made case sensitive or not by the use of switches Note that the command line switches for the linker are themselves case sensitive not all linkers and not earlier Microsoft and Borland linkers which is not something that you associate with the DOS command line Skeleton program Assembly for and against The Bare Bones Preamble The earlier theory will only really make sense when actual code is shown so in this chapter I have done a complete application a skeleton program that just puts Hi there on the screen Nothing too ambitious but the skeleton can be built upon for much more ambitious projects Its quite feasible to wr
179. PASCAL x y si Accessing the right data In this case you must do a late binding call because the SI value can have different values at execution time The CALL will automatically call the correct routine Use of THIS THIS is a pointer to the current object and is already introduced and discussed at length earlier in this chapter However this section will consider the rules of usage of THIS I have explained how SI is passed on the stack to the function Why pass it on the stack since SI will be the same value upon entry to the function anyway and can thus be accessed from the register C does it that way but your assembly program doesnt necessarily have to However it may be wise to stick with C conventions to enable smooth linking with C code You can see back in the class definition for WINDOW page 140 that I put an example data field labelled active Perhaps this is a flag indicating whether this is the active window or not whatever 146 Windows Assembly Language amp Systems Programming Obviously the instances window1 and window2 will have their own copies of active so the TEXTOUT function must access the active field in its own instance Thus if you have lea si windowl call si TEXTOUT PASCAL x y S1 Encapsulation SI would be passed to the function to let it know which object to communicate with For there is a general rule with OOP A function should only write to a
180. PC the plug in cards are most obvious These may include video printer serial communication and disk adaptor 188 Windows Assembly Language amp Systems Programming 8 bit ISA bus 16 bit ISA bus Reference book Auto co Afiguration of plug in cards Some PCs will have some of these on the motherboard rather than as plug in cards The socket into which these boards plug is basically an extention of the CPU bus with address data and control lines but usually it is in a Somewhat modified form Some expansion bus standards have become history such as MCA VESA local bus and EISA so I won t mention them further The ancient JSA Industry Standard Architecture standard is remaining popular and is on just about all new PCs New PCs usually have another bus for high speed known as the PCI Peripheral Connect Interface local bus Industry Standard Architecture ISA Early PCs use an 8088 CPU which despite advertisements is only an 8 bit CPU since it is based on the size of the data bus Hence the ISA bus also has only an 8 bit data bus Some early PC compatibles have an 8086 CPU which internally is identical to an 8088 but has an external 16 bit data bus As far as I am aware these machines still have only an 8 bit ISA bus The advent of the AT model PC with an 80286 CPU having a 16 bit data bus saw the introduction of the ISA bus with a 16 bit data bus So that 8 bit cards would still work the older co
181. Preamble This chapter is about interfacing assembly language with C and C and about one aspect of program design that is an outcome of the interface with C objects I have not gone into any general methodology of software design Programmers are migrating from C to C Ditto with other languages and of course the new kid on the block is Java You have got to think in terms of objects Early in 1991 I put a lot of thought into object oriented assembly language including the presentation of a paper I developed techniques for OOP but found the assemblers of that time to be somewhat inadequate So about mid 1991 I wrote to Borland in the USA explaining in detail what was wrong with their assembler and what it needed to be able to handle objects Then in February 1992 I was fascinated to learn that Borland had released a new assembler that they advertized as object oriented I like to think that I was one of their inspirations Why should you even bother with objects when programming at the assembly level The answer is very simple 1 To interface with 00 languages such as C 2 To improve the development and maintenance of the assembly language code 137 138 Windows Assembly Language amp Systems Programming What is OOP Windows assembly generic Windows 386 486 architecture OOP C Class Object instance The much touted advantages of OOP also apply to assembly language Do y
182. Programming 365 I began to wonder when the developers became very quiet for a couple of years but they were working frantically on the Windows version Figure 15 4 Layout fl Fe EH Ea I ermal Repeat Until wnt selected button Action was Cancelled pes End of Repeat Sai selected button Action was Cancelled Deactivate a Message Integrating with Assembly In line In many respects Layout gives you the best programming assembly environment My philosophy of the two extremes is applicable here you can merrily construct a flowchart then at any point in the flowchart you can stick in in line C C or assembly code It is a super high level language that allows in line assembly 366 Windows Assembly Language amp Systems Programming Figure 15 5 eee with assembly and modules Assembly in line In ae assembly aa aa ogram Execute Execute pa inside abView Assembly DLL Reference source inside pa Layout Each of the boxes in Figure 15 4 is called a blackbox and as with LabView they can be developed in another language In fact Layout blackboxes are simply DLLs That it write a DLL register it with Layout and it becomes a blackbox that you can put into your flowchart just like any other blackbox Figure 15 5 gives an overall picture Look at the figure and you can see how assembly language fits in with both Layout and LabView
183. R_PSP_ Segment Specifies the segment address of the TSR s program segment prefix PSP TSR API Ver_ID Specifies the version number of the structure TSR_Exec_Flags Specifies the execution flag This field must have one of the following values TSR_WINEXEC Execute a Windows based application TSR LOADLIBRARY Load a DLL TSR OPENDRIVER Load a driver This field is ignored if TSR_Exec_Cmd is 0 0 TSR_Exec_Cmd Show Specifies the flags for example SW_SHOWNOACTIVE to be passed to the WinExec function This field is ignored if TSR Exec Cmd is 0 0 TSR Exec Cmd Contains a 32 bit address segment offset of a command line string specifying the name and command line parameters of a Windows based application or a DLL This field should be 0 0 if automatic loading of a Windows based application or a DLL is not required TSR Reserved Contains 4 bytes of reserved space Do not use this field TSR_ID_Block Contains a 32 bit address segment offset of the TSR s ID block The first word in the block specifies the number of bytes in the block and is followed by the zero terminated ID string Windows uses the ID string to identify the TSR in error messages TSR_Data_Block Contains a 32 bit address segment offset of application specific data This pointer is not used by Windows it is included in the structure so that the TSR can communicate with other TSRs or with Windows based applications INDEX label scope modifi
184. S DOS programs use this function when they are idle such as when waiting for user input to allow 386 Enhanced mode Windows to run other programs that are not idle Call with Ax 1680h Return value The return value is 00h in the AL register if the function is supported Otherwise AL is unchanged contains 80h Comments Only non Windows programs should use Release Current VM Time Slice Windows applications should yield by calling the WaitMessage function A program can call this function at any time even when running in environments other than 386 Enhanced mode Windows environment If the current environment does not support the function the function returns and the program continues execution Windows suspends the current VM only if there is another VM scheduled to run If no other VM is ready the function returns to the program and execution continues A program should call the function eon for example once during each pass of the program s idle loop to give Windows ample opportunity to check for other VMs that are ready for execution Before calling this function a program should check that the Interrupt 2Fh address is not zero Interrupt 2Fb Function 1681h Begin Critical Section Prevents Windows from switching execution from the current VM to some other MS DOS device drivers and TSRs use this function to prevent a task switch from occurring Call with AX 1680h Return value This function has no
185. SM and TLINK however I m still using Microsoft s NMAKE To run this file NMAKE WINHULLO MAK fn winhullo all fn exe lpath borlandc lib path for libraries ipath borlandc include path for Include files epath borlandc bin path for EXEs sw c n v Tw L lpath switches for tlink n ignore default libs Tw generate Windows exe L lpath lib path v debug on i Note that these paths all assume you are in the same drive fn obj fn asm tasm zi fn High Level Assembly 125 r dont append to exe x dont look in INCLUDE environment variable for incl files i look in this P instead fn res fn rc re r x i ipath fn re cOws Windows small start up lib cwins Windows small Standard run time library cs Standard run time lib import access to Windows built in library functions fn exe fn obj fn def fn res tlink sw cOws fn fn fn import cwins cs fn def rc 30 x i ipath fn res Note that Borland C v2 5 names the Windows library CWINS LIB while v3 0 names it CWS LIB The Borlandc run time library is CS LIB which could be placed immediately after CWS if you need it Note that the S postfix designates the small model Note that if you use the tools from the SDK3 1 such as RC EXE and you want your program to work with both Windows 3 0 and 3 1 put 30 in second execution of RC
186. TCHMESSAGE PASCAL ss ax messageloop lea ax s2 call GETMESSAGE PASCAL ss ax null null null or ax ax jne mainloop GetMessage returns FALSE AX 0 if a quit message so here we are quiting mov ax s2 msWPARAM return wparam to windows OS quitwinmain ret WINMAINENDP Q w H Figure 5 1 Stack upon entry to callback Stack starts Stack Pointer SP aaa here PShdc An instance s3 of PSfErase PAINTSTRUCT PSrcPaint rcLeft is here s3 actually PSrcPaint rcT op equates to this point PSrcPaint rcRight BP 44 PSrcPaint rcBottom PSfRestore These field names w PSfIncUpdate are defined in PSrbReserved WINDOWS INC Note hDC equates to BP 12 amp dummy equates to BP 10 dummy 5 words Base Pointer BP register points here old BP 1 return address This is what FAR the stack looks lParam like at entry to the callback function after f the prolog hWnd 118 Windows Assembly Language amp Systems Programming PUBLIC s ee i ed WINASMIPROC WINASMIPROC PROC WINDOWS PASCAL FAR hWnd WORD msgtype WORD wParam WORD lParam DWORD LOCAL LOCAL LOCAL dummy WORD 5 hDC WORD s3 PAINTSTRUCT WINDOWS Notice two things here the WINDOWS qualifier and the qualifier dummy local variable Local declarations can take a repeat count which in this case declares five words the first pointed to by label dummy The WINDOWS qualifier takes care of generation of the special
187. T_ PTR DD 0 SIS _VIRT_ DEV FILE PTR DD 0 DOS Win Transitions 333 SIS_ REFERENCE DATA DD 0 SIS_INSTANCE_DATA_ PTR DD 0 SIS_Opt_Instance Data_Ptr DD 0 extra field Win95 only 3 i e if put 4 0 into first field WIN386_STARTUP_INFO_STRUC ENDS InstData Win386_Startup_Info_Struc lt gt TSR Info_Struc STRUC TSR Next dd TSR PSP Segment dw TSR API Ver ID dw 100h TSR Exec Flags dw 0 TSR Exec Cmd _Show dw 0 TSR Exec Cmd dd 0 TSR Reserved db 4 dup 0 TSR ID Block dd 0 TSR Data_ Block dd 0 TSR_Info_Struc ENDS tsr_info TSR_INFO STRUC lt gt Exec Path Name db C WINAPP EXE 0 0 path amp filename of windows app psp_size DW My ID Block dw My Name db TSR autoload WinApp amp VxD 0 My Name_End LABEL BYTE this ptr must get put into INT 60h INCLUDE GLOBL INC global data accessed by WINAPP VDEMOD globaldata GLOBALSTRUCTURE lt gt instanced here only but include file must be in other programs Data Notice the two data structures above TSR_INFO_STRUC and structures WIN386_STARTUP_INFO_STRUC GLOBL INC is not part of loading the VxD and WinApp it has to do with global data between all programs I have left out most of the ho hum installed portion of this TSR and reproduced only the interesting bits however you first need to examine the installation code Therefore I have turned this listing around and shown the install code immediately below DB 17 DUP 0 Resident part is abov
188. VM as performed by 2F 1685 though it appears that this will still function Instead I have used 2F 1683 to query the current VM mov ax 1683h int 2Fh returns VM id in BX cmp bx 1 l system VM je Standard i swith ta the system virtual machine and call the forwarder program mov ax 3561h get int 61 vector address int Zh gt ES BX mov ax 1685h k fen 1685 Switch VM s and callback mov di bx ES DI callback address int 61 hdlr mov bx 1 BX VM to switch to system VM mov cx 3 xor dx dx DX SI priority boost zero xor si Si es int 2Fh switch to system VM and do INT 60 exit4 Restore host PSP restore old break setting and IVT vectors 1Bh 23h and 24h Restore host stack popa restore registers POP ds i pop es i popf E Windows provides various extensions to INT 2Fh as introduced in Chapter 9 Int 2F AX 1683h queries the current VM No parameters are supplied to it and it returns only one value the VM ID number in BX We expect the system VM to be number 1 however it is possible to confirm this after Windows has initialized all virtual device drivers it then calls INT 2F 1608h to inform the DOS device drivers or TSRs Windows supplies the system VM ID number with thiscall 328 Windows Assembly Language amp Systems Programming mov cs isrbusy 0 allow reentrance 1ret return from interrupt callback this is the forwarder entered from the signaller
189. W returns Since CREATEWINDOW itself sends messages to exportwndproc the latter has to test pwindowflag and disable normal processing until it is set mov si hwnd ax save handle in window object mov di ax or ax ax exit if handle is 0 jz endhere call SETWINDOWWORD PASCAL di O si mS addr of window object in Windows internal data at offs 01 mov pwindowflag 1 enable callback normal processing Callback disabled above but my callback needs WM_CREATE So send it now One deviation leads to another a problem arises because CREATEWINDOW sends the WM_CREATE message to the callback which my exportwndproc has ignored due to pwindowflag being cleared However now that SETWINDOWWORD has done its job pwindowflag has been set I have used SENDMESSAGE to resend the WM_CREATE message Now it goes to the callback via all the usual rigmarole the application queue and the message loop and is processed in the normal way calling the create routine call SENDMESSAGE PASCAL di WM CREATE 0 p 0 0 last 2 are incorrect call SHOWWINDOW PASCAL di mainl ncmdshow call UPDATEWINDOW PASCAL di mov ax 1 ET endhere WINDOWmake ret ENDP If you have done much Windows programming you may have noticed something missing a test for hPrevInstance followed by a conditional jump Actually it isnt really needed 170 Windows Assembly Language amp Systems Programming
190. WIN ASM gt TSR2WIN EXE this is a windows aware tsr that is loaded before windows When windows loads this tsr will automatically cause a windows application to start and will automatically load a virtual device driver This tsr must not be a separate file fad sais specified as the dos stub for the virtual device driver VxD that is to be automatically loaded if your only requirement is to auto load a windows app then you can have this tsr stand alone or as stub for the WinApp the windows application is called WINAPP EXE sthe virtual device driver is called VDEMOD EXE pm WINAPP must be in the root directory or path spec d below VDEMOD EXE can be anywhere An interesting aspect of this tsr is that it creates a global data structure and passes a FLAT 32 bit pointer via the IVI WINAPP and VDEMOD can access this pointer Note that this is a EXE file but data is in the code segment makes it easier to make into a tsr 286 MODEL SMALL STACK DATA CODE start jmp installhooks winloaded DB 0 dpmiloaded DB 0 winmode DB 0 oldoffivt2F Dw 0 2F saved vector oldsegivt2F DW 0 oldoffivtic DW 0 1C saved vector oldsegivtic DW 0 oldoffivt9 DW 0 oldsegivt9 Dw 0 oldoffivt28 DW 0 oldsegivt28 DW 0 bypass1C DB 0 fix reentrancy problems bypass28 DB 0 dosbusyoff DW 0 dosbusyseg Dw 0 WIN386_ STARTUP_INFO_STRUC STRUC SIS VERSION DB 3 0 3 0Ah for Win3 1 SIS NEX
191. WINVER EQU 0300h 2 WINPROLOGUE EQU 1 forces win prolog epil on far procs INCLUDE winasm60 INC this is not the same WINDOWS INC used ly the TASM programs It is generated by H2INC EXE and contains prototypes Generated by H2INC C Gc WINDOWS H IDM QUIT EQU 100 menu identifiers must be IDM_ABOUT EQU 101 same as defined in RC file EXTRN __astart FAR startup code in APPENTRY OBJ referenced at END DATA szwintitle DB HULLO DEMO PROGRAM 0 SZASMDEMOname DB ASMDEMO2 0 hOemFont DW 0 handle to OEM font soutstring DB Hullo World szaboutstr DB Assembly Language Windows Demo 0 messagebox sztitlestr DB Karda Prints 0 CODE PUBLIC WINMAIN WINMAIN PROC NEAR PASCAL hInstance WORD hPrevinstance WORD lpCmdLine LPSTR nCmdShow SWORD LOCAL hWnd HWND LOCAL 1 WNDCLASS LOCAL S2 MSG cmp hPreviInstance 0 0 if no previous instance je yeslst imp createwin yesist Setup the window class structure for REGISTERCLASS High Level Assembly 133 mov si Style 3 lea di si lpfnwndproc mov di OFFSET ASMDEMOPROC mov di 2 SEG ASMDEMOPROC mov sl CbClsExtra 0O mov sl CbWndExtra 0O mov ax hInstance mov sl HInstance ax invoke LOADICON null ID1 APPLICATION mov s1 HIcon ax invoke LOADCURSOR null IDC_ ARROW mov sl HCursor ax mov sl hbrBackground COLOR _ BACKGROUND mov ax OFFSET szASMDEMOname lea di sl1 lpszmenuname mov di ax mov di 2 ds lea di sl lpszclas
192. Windows services or functions do all that many programmers would want though we dig a little deeper in this book and also show how useful the INT services can be Real Mode Interrupts Interrupts whether from an external source hardware or generated internally by the program software cause the same reaction in the CPU 1 The CPU pushes the current Instruction Pointer IP Code Segment CS and FLAGS register onto the stack 2 Then the CPU uses the value n as an index into the Interrupt Vector Table IVT where it finds the FAR address of the service routine 34 Windows Assembly Language amp Systems Programming IRET instruction CALL to an ISR PUSHF 3 The CPU then loads the FAR address into its CS IP registers and commences execution of the service routine 4 Interrupt routines always terminate with an IRET instruction which has the effect of popping the three values saved on the stack back off into CS IP and FLAGS Thus the CPU carries on as before as though nothing had happened Note that when a CALL instruction executes it works in a similar way but a FAR CALL only saves CS and IP on the stack not the FLAGS Also if it is a NEAR CALL only IP is saved on the stack In addition the routine called must terminate with RET not IRET as the latter pops three values off the stack expecting FLAGS to be on there as well Incidentally a useful point arises from what I have written above You c
193. Windows 95 is preemption Actually whether it be Windows 1 O or 95 interrupt driven device drivers including keyboard input must always be working in the background When a key is pressed a hardware interrupt is generated which invokes the keyboard device driver The immediate response to a key press is preemption nothing else and contrary to common knowledge Windows 3 x applications can make use of similar mechanisms Also the DPMI host maintains preemptive time sliced switching between VMs on Windows 3 x and 95 A Windows application can respond immediately to an external hardware event or a timer interrupt for that matter refer back to page 246 for a brief introduction to the PCs hardware timers and to pages 239 for an introduction to the Windows software timers 249 250 Windows Assembly Language amp Systems Programming Preemption by interrupts Hooking an interrupt Hardware vs software interrupts You can also signal between Windows applications immediately without going through the messaging mechanism Just as device drivers can be interrupt driven so too can your own application to provide predictable real time response It is not all peaches and cream however The chapter starts with code for software interrupts because it is the easier case The interrupt mechanism is particularly useful for signalling and passing data between Windows programs The chapter then progresses to hardware
194. XTOUT Notice that I didnt have to give the new procedure a different name Then I declared three static instances permanently in the data segment I could have made them automatic simply by moving them down into main 144 Windows Assembly Language amp Systems Programming gt The code within main shows how easy it is to call the function object associated with a particular object A call to this function means pointer that TEXTOUT will execute but will automatically work on the data and functions that are part of the referenced object This is because the THIS pointer is passed on the stack see page 140 The example of late binding may look rather complicated ptr is a label that is a pointer to data of type WINDOW The simply declares that it is a pointer The data type tells C that ptr can only be used to address objects instances of WINDOW The next line sets ptr to point to windowl The following line uses ptr to call windowl TEXTOUT This line corresponds exactly with the assembly language code call sil TEXTOUT PASCAL valuel value2 si I have used the PASCAL qualifier here rather than C for consistency with later examples It does cause some differences such as reversed order of stack pushing and stack clean up For more specific details see ahead to the section Interfacing With C on page 147 Compiler It is interesting to analyse how the compiler decides whether to optimisation compil
195. a I have mentioned TASM s apparently anomalous handling of local symbols LOCAL data of course exists on the stack and is created on entry to a procedure and destroyed on exit However it will still be in existence at lower level nested eee ee es er e lap at gt a T LV Q AT Pa eae oe pl Pees cere ee Pa S 4K L a ra A laa a a f RC file High Level Assembly 123 procedure A will be accessable by procedure B if procedure B is nested within called from within procedure A What Im talking about here is the availability of the data not the scope of the symbols Scope is discussed above and varies with MASM and TASM There is no problem with the availability of procedure A data conceptually because procedure B will be using the stack further down in memory The stack grows with a procedure call and shrinks upon exit What is not so apparent is that any LOCAL data declared in WinMain is also available in a callback A callback is not what you immediately think of as being nested within WinMainQ but it is even though the call to it has gone via DispatchMessage and Windows See Figure 5 2 Figure 5 2 Accessing WinMain local data After prolog Stack grows Entry point Callback LOCAL to callback data After prolog Stack grows Entry point WinMain LOCAL to WinMain data See eee Assembling and Linking Thats it a complete assembly language program Of course you do need those other files to assem
196. a picture of the CPUs registers in Figure 1 11 INT 15h AH 87h moves a block of data between conventional and extended memory A use that immediately comes to mind with this is a TSR manager that could keep them all out of the way and bring one back as needed there are such managers available A problem with Protected mode is all the housekeeping required that is the various tables required for addressing The segment registers no longer have the actual addresses they are kept in the Local Descriptor Tables LDTs or the Global Descriptor Table GDT Furthermore if interrupts are to be handled by the program in Protected mode an Interrupt Descriptor Table is required There s more if task switching is to be supported a Task State Segment TSS is required for each task Fortunately INT 15h AH 87h keeps it simple All that is required is a GDT to get the service to work and it is up to the application program to set this up The service requires CX Number of words to transfer ES SI Physical address of GDT in conventional memory AH 87h The DOS service takes care of differences between switching the 286 and 386 in the 286 it involves setting the Protect Enable bit in the Machine Status Word register setting up descriptor tables and loading the address of the GDT Global Descriptor Table into the GDT pointer register In both the 286 and 386 getting into Protected mode involves setting certain bits in
197. able VM Assisted Save Restore Interrupt 2Fh Function 4000h should avoid accessing video memory and registers to avoid being frozen Applications that have not called Enable VM Assisted Save Restore call access video memory and registers since the VDD saves these after this function returns Interrupt 2Fh Function 4002h Notify Foreground Switch Notifies a VM application that it has been switched to the foreground and can now access the video memory and registers without being frozen The virtual display device VDD calls this function Call with AX 4002h Return value This function has no return value Comments If the VM application has called Enable VM Assisted Save Restore Interrupt 2Fh Function 4000h VDD restores the video registers to their state prior to the call to Enable VM Assisted Save Restore the application is responsible for restoring video memory If the VM application has not called Enable VM Assisted Save Restore Interrupt 2Fh Function 4000h the VDD automatically restores both video memory and registers 410 Windows Assembly Language amp Systems Programming IAT Heading Description Call with Returns Comments Under certain error conditions the VDD may call this function without calling a corresponding Notify Background Switch Interrupt 2Fh Function 4001h Interrupt 2Fh Function 4003h Enter Critical Section Notifies the virtual display device that the VM application
198. addresses The CPU adds the offset IP to Free memory joowawand the segment address CSx 16 giving a 20 bit physical address Real Mode The 8088 8086 operate in what we now call Real mode This means that the segment registers hold real addresses in accordance with Figures 1 7 and 1 8 The 286 386 etc chips also run in Real mode when first turned on and employ the same 20 bit segmented addressing mode For the sake of compatibility the more advanced CPUs can only address 1M and the extra address lines are inactivated High The fundamental problem with DOS and DOS applications is the memory 1M limit There is however a qualification to this Real mode addressing can address over the 1M limit by an extra 64K known as the high memory segment A quick look at Figure 1 8 will show why If we put maximum values in them that is CS FFFF and IP FFFF the computed 20 bit address is 1OFFEF The 1M limit is FFFFF The 21st The 20 bit upper limit is FFFFF hex 1M 1 but the offset IP address bit allows in theory at least addressing just over this Physically this would require a 21st address bit which the 8088 8086 don t have and it s disabled on the 286 etc chips also But the PC can be instructed to turn on the 21st address bit on the 286 386 chips thus allowing them access to that 64K above the 1M 18 Windows Assembly Language amp Systems Programming Using segment registers in a program Selectors An ext
199. alid value BX CX SIDI 0 8023h invalid handle In SEDD Int 31h Function 0600h Lock Linear Region Locks the specified linear address range Call with AX 0600h BX CX starting linear address of memory to lock SI DI size of region to lock bytes Returns if function successful CF clear if function unsuccessful CF set AX error code 8013h physical memory unavailable 8017h lock count exceeded 8025h invalid linear address unallocated pages Int 31h Function 0601h Unlock Linear Region Unlocks a linear address range that was previously locked using the Lock Linear Region function Int 3 1 h Function 0600h DPMI Services 397 Call with AX 0601h BX CX starting linear address of memory to unlock SI DI size of region to unlock bytes Returns if function successful CF clear if function unsuccessful CF set AX error code 8002h invalid state page not locked 8025h invalid linear address unallocated pages Int 31h Function 0602h Mark Real Mode Region as Pageable Advises the DPMI host that the specified memory below the 1 MB boundary may be paged to disk Call with AX 0602h BX CX starting linear address of memory to mark as pageable SI DI size of region to be marked bytes Returns if function successful CF clear if function unsuccessful CF set AX error code 8002h invalid state region already marked as pageable 8025h invalid linear a
200. allback function e NOTIFYUNREGISTER Removes a notification callback function e STACKTRACECSIPFIRST Retrieves information about a stack frame e STACKTRACEFIRST Retrieves information about the first stack frame STACKTRACENEXT Retrieves information about the next stack frame e SYSTEMHEAPINFO Retrieves information about the USER heap e TASKFINDHANDLE Retrieves information about a task e TASKFIRST Retrieves information about the first task in the task queue e TASKGETCSIP Returns the next CS IP value of a task e TASKNEXT Retrieves information about the next task in the task queue e TASKSETCSIP Sets the CS IP of a sleeping task e TASKSWITCH Switches to a specific address within a new task e TERMINATEAPP Terminates an application e TIMERCOUNT Retrieves execution times Windows 95 replaces all of the above with the following e CreateToolhelp32Snapshot Takes a snapshot of the Win32 processes heaps modules and threads used by the Win32 processes e Heap32First Retrieves information about the first block of a heap that has been allocated by a Win32 process e Heap32ListFirst Retrieves information about the first heap that has been allocated by a specified Win32 process e Heap32ListNext Retrieves information about the next heap that has been allocated by a Win32 process e Heap32Next Retrieves information about the next block of a heap that has been allocated by a Win32 process e Module32First Retrie
201. alue of C hex means that it is a call gate to a 32 bit 386 segment For the record the other possible values are 5 task gate 6 286 interrupt gate 7 286 trap gate E 386 interrupt gate and F 386 trap gate The Selector field is the ring O segment that we want to call and Offset is where in the segment Note that the code descriptor for the ring 0 selector still has to exist and it will be elsewhere in the LDT or GDT App_system would normally be zero and Present set to 1 The DPL field is important it specifies the least privileged code that is permitted to use this call gate Therefore we set it to 3 Putting call If we create a call gate we can then put it in the LDT or GDT and gate amp thus we will have a selector for it Then all we need to do in our descriptor program is call the selector the CPU will recognize it to be a call together gate look inside it and get out the selector offset The CPU will 294 Windows Assembly Language amp Systems Programming then use that selector to get the code descriptor and will call the code Note however one peculiar thing if you perform a FAR call from your application to the call gate selector at some offset any offset that you specify is ignored Instead the offset in the call gate is used At this point I think it best to show some code Ring Transition Example Code This first code extract shows just one example of how we could set up addressing of the r
202. amming FORMAT Heading Description Call with Returns Comments Interrupt 2Fh Function 1685h Switch VMs and CallBack Directs Windows to switch to a specific virtual machine and begin execution After Windows switches it calls the specified callback function allowing a device driver or TSR to access the data associated with the specified virtual machine This function is typically used by MS DOS device drivers and TSRs that support networks and that need to perform functions in a specific virtual machine Call with 1685h Ax BX Virtual machine ID CX Flags Specifies when to switch This parameter is a combination of the following bit values Bit Meaning 0 Set to 1 to wait until interrupts are enabled Set to 1 to wait until critical section is released All other bits are reserved and must be 0 DX SI Priority Specifies the priority boost for the virtual machine It can be one of the following values Value Meaning Critical Section Boost VM priority boost amp d by this value when Begin_Critical_Section is called Cur Run VM_Boost Time slice scheduler boosts each VM in turn by this value to force them to run for their allotted time slice High _Pri_Device_Boost Time critical operations that should not circumvent the critical section boost should use this boost Low_Pri_Device Boost Used by virtual devices that need an event to be processed in a timely fashion but that are not extreme
203. ams cannot work above 1M The 286 386 etc CPUs can be switched into what is known as Protected mode which allows memory access up to the 16M or beyond limit but the real addresses have to be dumped from the segment registers Instead they contain selectors or indexes into tables and the tables have the real addresses of the segments DOS does have some mechanisms for switching into and out of Protected mode and a couple of early DOS services are introduced here DOS Protected Mode Programming Oh what a can of worms I didn t quite know where to start as there are so many considerations I have written about the problems at least some of them of running DOS applications in Protected mode and DOS s own failure in this regard INT 15h INT 15h AH 88h AH 87h Local and global descriptor tables Switching the CPU into Protected mode Machine Status Word CPU Architecture 19 However Microsoft gradually extended DOS and one of the first services they added was the functions invoked via INT 15h So I ll start with these The idea was to provide some means of switching from Real mode to Protected mode and back to transfer code to and from conventional and extended memory and to transfer execution from a Real mode program to a Protected mode program INT 15h AH 88h will tell us how much extended memory there is though not how it is being used It simply returns with a value in the AX register There is
204. an use the CALL instruction to call the BIOS and DOS services despite the fact that they terminate with an IRET push flags on stack CALL rou tinename Structure of the IVT Interrupt Descriptor Table IDT That is you push the FLAGS on beforehand using a special instruction PUSHEF there is also a POPE You do need to know the address of the routine that you are calling however since it doesn t make use of the IVT as INT does Protected Mode Interrupts Just as segment registers no longer represent real addresses so too the interrupt mechanism no longer uses the Interrupt Vector Table IVT Interestingly when Windows is running the IVT is still there but our applications don t use it It is still used by Windows but that s another story So just where is this IVT Have a look back at page 11 The IVT sits in RAM right down at O0O0 O00O0 occupying the first 1024 bytes It is set up by the BIOS startup routine and filled in by DOS also The fundamental problem is that it contains real segment addresses which is a no no in Protected mode though is ok in virtual 86 mode Therefore a special table has to be created by the Windows operating system called the Interrupt Descriptor Table IDT which contains the linear addresses of the services Linear addresses are real but they are actual 24 or 32 bit addresses without the segment offset structure Using INT within WinApps Redirection of IDT to IVT
205. and to the for that you need DPMI service 0200h Get Real Mode Interrupt above Vector The vector obtained is in the form of segment offset typical which cannot be used while your program is in Protected mode So problem then you need DPMI service 0002h Segment to Descriptor which will create a descriptor for the segment offset address and will return a selector 0002h was introduced on page 228 Problem solved Real mode Figure 11 1 relied upon a Windows handler to transfer control to execution the original Real mode routine but this only works for the versus data recognized BIOS and DOS services Any other interrupt will most access likely crash The question of an interrupt being reflected down to Real mode or not is a different question from the typical problem above in which it was necessary to look at a certain offset inside the Real mode code I will not worry too much about the various scenarios that will require you to access Real mode software just think for now what the solution is I outlined above how to locate a Real mode routine for data access but what if you want to call it DPMI to the rescue again Routine to calla Real There s an invaluable service 0300h that does everything Some mode ISR code will illustrate DATA regstruc STRUC Real mode register data structure edil DD 0 esil DD 0 ebpl DD 0 resl DD 0 ebxl DD 0 edxl DD 0 ecxl DD 0 eaxl DD 0 flagsl DW 0 esl DW 0 270 Windows Assembly Language
206. and JRET other drivers have the option of doing this also which is why we called the old vector Windows also supplies ES BX 0 0 in Standard mode DS SI 0 0 DX bit 0 1 if Windows in Standard mode 0 if Enhanced mode and DI contains the version number 030Ah for version 3 1 This is the opposite of 1605h called by Windows when it unloads Windows supplies DX bit 0 for Standard mode and 0 for Enhanced mode endprog int93 ENDS END Some coding issues Outline of DOSTSR operation Data contention DOS Win Transitions 329 install The entire program was too much to print hence the sections in italics The complete program is on the Companion Disk however if you know much about TSRs there is sufficient information in this listing for you to construct it One interesting little point about this code is that we obviously dont want to try jumping VMs if Windows isnt even loaded and indeed the INT 2Fh extensions are not even available until Windows is loaded At one stage in the program development I did call INT 2F 1685h to switch VMs before Windows had loaded and before I had put in the winloaded checking and it worked Or rather the switch didnt take place so nothing happened However on another computer it crashed The only difference I can see is that the one that worked was running DRDOS version 6 and the one that failed was running MS DOS version 5 At this stage of
207. and the ISR could have read the parameter from the input port and recorded it then exited Simple enough You will find the program on the Companion Disk in ISR1 Direct Memory Access In this and the previous chapters I have covered the basic elements of hardware access namely direct memory access I O port access and interrupts but there is another aspect that is worth introducing DMA DMA is perhaps somewhat too esoteric for a book of this general nature however a few notes are in order and I can point you in the right direction The best reference would be Microsoft s Virtual DMA Services Specification part number 098 10869 Another introductory reference is DMA Revealed by Karen Hazzah Windows DOS Developer s Journal April 1992 pages 5 20 Basically DMA takes the job of data transfer away from the CPU for the sake of speedy transfer of blocks of data usually between a hardware device and memory It requires a DMA controller chip Initialization involves telling the controller the address of the memory buffer and how many bytes to transfer Bolting a f segment down INT 4Bh Real Time Events 265 With Windows there are complications because the CPU can be in Real or Protected mode In Protected mode the buffer should be constrained to be below 1M and should also be contiguous Paging normally will split a segment up all over the place but there are mechanisms in Windows for keeping a segmen
208. and your callback just sends them back to Windows again for final default processing Default DefWindowProc is a kind of rubbish bin for messages that you message don t know what to do with And believe me there are a lot of handling them After sending the message to its final resting place or handling it in some way within the callback execution returns to the next statement after DefWindowProc which is usually a return from the callback function designated by above or by a RET instruction in assembly However this will take execution back to Windows again Figure 3 3 Event driven structure APPLICATION WINDOWS WinMain function Start Windows calls WinMain GetMessage Wait until an event occurs related to your application application can preprocess message DispatchMessageQ Windows calls the application s callback function This processes the messages WndProc will return back here and hence to the message loop Noop back funless exit condition WndProc function _ case structure for processing messages Default processing of messages then return to WinMain via WndProc and Windows oat indowProcQ Follow this tangled path right through Opening Windows amp 1 Windows will return to the statement just after DispatchMessage so we are back in the main loop The main loop is an endless loop executing GetMessage then Tr
209. anslateMessage then DispatchMessage though there is a test for exiting Figure 3 3 puts the whole lot together pictorially A word of advice don t let this confuse you See the simplicity behind all of the detail Windows sends messages to a window and your program can have as many windows as it wants The message goes via WinMain to the callback function for that window where you can respond to it If you don t know what to do with the message just call DefWindowProc End of story Data Types Hungarian Tabulated in Table 3 1 are prefixes to data and pointer labels It is convention known as the Hungarian convention and is the voluntary prefixing of data labels with a character or characters to indicate the type of content Table 3 1 Data types PREFIX MEANING SIZE COMMENTS b Boolean value WORD 0 false non zero true Character BYTE Extended ANSI character code fe Long unsigned pena Unsigned value integer f Bit flag value WORD 16 individual flags lh Handle WORD Handle of a resource Long integer value DWORD Long pointer DWORD FAR pointer Short integer value WORD Signed value Short pointer WORD _ NEAR pointer pt x y coordinate point DWORD nsigned 2 word value rgb RGB color value DWORD Unsigned Short unsigned WORD Unsigned value integer igned value lees ro 82 Windows Assembly Language amp Systems Programming Reference source Other pre
210. ard Transmit timeout error to keyboard 0 Inhibit keyboard from keyboard lock switch 0 Data was just sent to 8042 via port 60h Data was last sent to 8042 via port 64h 0 Power on caused reset 1 8042 self test completed successfully 0 A write can be made to port 60h or 64h 1 No writes allowed to port 60h or 64h 0 A read from port 60h will not be valid Data available use port 60h to read them There are a whole lot of commands that you can send to port 64h Of course this presumes that you are not using an IBM XT PC If your software is to run on AT class machines only including MCA EISA PCI then you may have to state that fact with the documentation and or your software could perform a simple test For example the AAh command to port 64h is a self test and if the keyboard controller passes the self test it will return the value 55h in port 60h The XT would not respond to this at all Of course what you read from port 60h in an XT could accidentally though very unlikely be scancode 55h Some of these commands result in data returned via port 60h but as noted above you must read port 64h in a loop testing bit O Further details such as the commands that port 60h can send to the 803 1 are to be found in The Undocumented PC by Frank Van Gilluwe Addison Wesley 1994 For further details on keyboard interrupt handling refer to Chapter 10 PC Expansion Buses If you look under the lid of a
211. arlier in this chapter We will do a number of passes through the same topics as the chapter progresses going a little deeper each time So to find out more about the registers memory etc read ahead Figure 1 4 Memory map of the PC ADDRESS 0000h CONTENTS Interrupt Vector Table This is a memory map of the 00400h BIOS data area PC Any of the x86 CPUs 00500h DOS data area running in Real mode which is the default at power on only utilise a 20 bit address bus so only address up to IM This is referred to as the conventional memory while that above 1M is Resident part of DOS device drivers amp TSRs Free memory Transient part of DOS 640K dec A0000h extended memory oor hie o e e B8000h and ROM hardwired into C0000h fixed addresses and in some C8000h locations there may be Aes ane P4000h F6000h FEOOOh ROM BIOS 64K higher memory area memory Extended 12 Windows Assembly Language amp Systems Programming Size of the address bus The famous 640K limit Scan for extra ROM Memory Map of the PC The 8088 and 8086 have a 20 bit address bus which means that they can address 2 _ 1 FFFFF hex 1 megabytes decimal The 80286 has 24 bits and the 80386 has 32 bits A good starting point is at the beginning For the 8088 6 the memory organisation on the PC looks like
212. as it was in the DOS only days The same thing goes for locking segments in place the Windows textbooks make a noise about how this is undesirable yet in reality it isnt if you dont lock too many bytes this is assembly language remember super compact Lock as many segments as you want and even lock them in the first 1M if you want Note that Windows has DOS Win Transitions 325 functions for this see above and so does DPMI apart from the specifications in the DEF file Put those TSRs in that first 1M and dont worry about it My little DOS TSR hardly impinges on the valuable 1M anyway its under 300 bytes It hooks INT 9 which is a special case hardware interrupt Here it is somewhat abridged DOSTSR ASM Hardware interrupt keyboard handler for Windows 286 int9 SEGMENT BYTE PUBLIC CODE ASSUME cs int9 ds int9 ORG 100h install jmp start oldoffivt2F DW 0 jsave old int 2F vector here oldsegivt2F DW 0 4 winloaded DB 0 set when Windows is loaded amp viceversa winmode DB 0 bit 0 1 if Standard 0 if Enhanced oldoffivt9 DW 0 save old vector here oldsegivt3 DW Cree oldss DW 0 host stack oldsp DW 0 i tsrpspseg DW 0 seg addr of psp isrbusy DB 0 set to prevent reentrance start mov tsrpspseg es save psp seg addr Test if this TSR already installed TE S Get oul Code for synchronizing and co existing with DOS save segment address of this PSP get address of inpos
213. as its own set of APIDLLs see page 235 However we can mix and match with caution of course The process of translating between 32 and 16 bit code is known as thunking and Windows 95 provides two mechanisms Generic thunking and Flat thunking Flat thunking is specific to Windows 95 it is not portable to Windows NT It allows 16 to 32 bit and 32 to 16 bit function calls so it is most flexible Generic thunking works on both Windows 95 and NT but only allows a 16 bit application to call 32 bit functions not the other way around Universal thunking is for Windows 3 1 applications to access the win32s API A good explanation of Flat thunking is to found inInside Windows 95 by Adrian King Microsoft Press USA 1994 Also look at the Win95 SDK CD ROM Generic thunking is also explained in the Win95 SDK CD ROM in file DOC MISC GENTHUNK TXT The following information is based on this and other documents on the SDK CD ROM Another excellent document that covers both Generic and Flat thunking and has detailed descriptions of all the Generic API functions is Programmers Guide to Microsoft Windows 9 5 by the Microsoft Windows Development Team Microsoft Press USA 1995 Generic Thunking Windows on Win32 WOW presents 16 bit APIs that allow you to load the Win32 DLL get the address of the DLL routine call the routine passing it up to thirty two 32 bit arguments convert 16 16 WOW addresses to 0 32 address
214. ase 8 15 Readable Conforming Base 1 6 23 Code data App_system Access byte pete 6 DPL Present Base_24_31 Limit_16_19 Bits O 3 in offset 6 of a Unused descriptor is the upper part Always 0 of the size of the segment Seg_16_32 Granularity High part of the linear starting address bits 24 3 1 The vital bit in this descriptor is bit 6 in offset 6 labelled Seg_ 6_32 If this is set the CPU is in 32 bit mode When the Granularity bit is cleared the limit value is the size of the segment expressed as number of 4K pages or if set the limit value expresses size in bytes DPL meaning descriptor privilege level is the level of this segment Present is set if the segment is physically present in memory You likely will not need to modify the other fields of the Access byte 290 Windows Assembly Language amp Systems Programming Instruction size prefix 0907 0200 0907 0201 32 bit default The current mode of the CPU whether 16 bit or 32 bit is determined by Seg 16 32 If it is set the 32 bit registers are enabled and just about all operations become 32 bits This includes PUSH and POP operations on the stack However this does not preclude you from using parts of the 32 bit registers such as AL AH and AX in EAX Just to keep confusing you even if the the segment is in 16 bit mode you can still use the 32 bit registers For starters Pll take the case of an old fashioned Windows app
215. at an IRET from an interrupt routine may not set the flag as it was prior to the interrupt For more information on I O refer to page 244 Task Switching Considering the complications of multitasking I sometimes wonder if it is all worth it Perhaps a more effective solution would have been multiple CPU boards each single tasking Anyway we are stuck with the current situation Changing from one task program to another is a matter of changing to a new LDT which involves the CPU looking into the GDT and getting the new LDT s address However the state of the task about to be suspended must be saved and the state of the incoming task must be restored This state consists of the CPU and coprocessor registers plus various memory pointers and values and an incredible time overhead is involved to save and restore this lot The CPU has to maintain a special segment for each task called the Task State Segment TSS into which all of this goes Then of course the CPU must keep track of where these TSSs are so it maintains descriptors for the TSSs in the GDT Thus the GDT contains more than just descriptors for the LDTs Windows 3 x and 95 have only one LDT for all applications whether in Standard or Enhanced modes which is a compromise in its design that can potentially cause trouble This limitation tallies with DPMI version 0 9 which in Windows maintains one LDT per virtual machine not per task Windows is see
216. ata selector REPAINTSCREEN Not described in SDK Tells the GDI to repaint the entire display e RESURRECTION Not documented in SDK Turns on Windows display driver See the example Chapter 9 Complement is DEATH SELECTORACCESSIUGHTS Not described in the SDK Sets the attributes of the specified selector in the descriptor table SETSELECTORBASE Not described in SDK 3 0 Sets the linear base address of the specified selector in the descriptor table SETSELECTOIUIMIT Not described in SDK 3 0 Sets the limit of the specified selector in the descriptor table 212 Windows Assembly Language amp Systems Programming L ow level GD functions Low level Comm functions e SETWINDOWSHOOK Installs a system and or application filter function Applications specific to Windows 3 1 should use SETWINDOWSHOOKEX e THROW Restores the execution environment to the specified values Complement is CATCH e UNHOOKWINDOWSHOOK Removes a Windows filter function from a filter function chain Complement is SETWINDOWSHOOK Applications specific to Windows 3 1 should use UNHOOK WINDOWSHOOKEX Supported but recommend UnHookWindowsHookEx e SETWINDEBUGINFO Only available with Windows 3 1 Sets current system debugging information e WINEXEC Executes a separate application Supported but recommend CreateProcess e YIELD Halts the current task and starts any waiting task There is a group of low level GDI functions
217. ata label prefixes Get Translate Dispatch Message C Syntax The code sample should be readable even if you don t know C Note that some of the Windows textbooks give the basic program structure in classical C not ANSI C and I have stuck with that You will notice amp msg specified as a parameter and this may need some clarification to those unfamiliar with C It should become clear later on when you see it in assembly language This function requires that an address to which the returned message can be placed be provided as a parameter The amp means address of in this case the address of a data area labelled as msg not defined in listing You will also notice the PASCAL qualifier in the declaration of WinMain This is because Windows 3 x uses Pascal calling conventions not C conventions So the override is needed This is explained in more detail later see page 112 if the fancy takes you and a note was made earlier on page 72 You might like to glance ahead to Chapter 13 to see a complete 32 bit application written in assembly language There you will see the procedures default to the STDCALL convention as specified in the MODEL directive see page 111 This is a mixture of C and Pascal in which parameters are pushed onto the stack from right to left and stack cleanup is performed by the called procedure I suppose this is as good a place as any in which to introduce the Windows label
218. ation 203 DPMI Toolkit 323 Flow Design for Embedded Systems 359 368 GOOFEE 359 368 Inside Windows 95 219 Interfacing to the IBM Personal Computer 188 LabView 363 Layout 366 Making Windows amp DOS Progr s Talk 275 Mewel 227 Mixed Language Programming with Asm 368 MSDN 339 OOP in Assembly Language 159 Programmer s PC Sourcebook 82 Radbum Wayne MASM skeleton 317 Ralph Brown s Interrupt List 242 Soft ICE W 346 Unauthorized Windows 95 235 346 Using DPMI to Hook Interrupts 277 Virtual DMA Services Specification 264 VxD Lite 340 WALK32 MASM development suite 317 Windows 95 Systems Programming Secrets 346 Windows Developer s Notes 198 Windows Programmer s Reference 198 Writing Windows Device Drivers 203 Index 4 9 PEOPLE Abrash Michael 367 Brown Ralph 242 Eggebrecht Lewis 188 Hazzah Karen 264 Hyde R 159 Hogan Thorn Kauler Barry 359 3 King Adrian 219 Norton Daniel 203 247 344 Olsen Thomas 275 Oney Walter 277 Pietrek Matt 218 288 346 Radbum Wayne 317 Schell Rick 368 Schreiber Sven 317 Schulman Andrew 218 235 346 Williams Al 291 NOTES The DPMI Specification is available from Intel order number 240977 001 Enauire with vour local Intel office or the Intel Literature Distribution Center P O Box 7641 Mt Prospect IL 60056 7641 USA 2 The specific reference for Appendix D is the Device Driver Adaptation Guide Microsoft Device Development Kit version 3 1 1992 Microsof
219. ation services These enable Protected mode programs to call Real mode software directly They also provide the reverse e DOS memory management services These work like the DOS INT 21h functions 48h 49h and 4Ah but work from Protected mode They automatically create and destroy descriptors so that memory blocks can be accessed easily from Protected mode e Debug support services These set and clear watchpoints used by debuggers e Miscellaneous services These provide information about DPMI support for the Display driver services BIOS DOS Windows_ Services 20 5 creation of TSRs direct access to memory mapped peripheral devices interrogation of the numeric coprocessor status and emulation of the coprocessor INT 2Fh Extensions Apart from the DPMI extensions to INT 2Fh provided as part of the DPMI Windows also provides other extensions Functions 4000h to 4007h are for use with the display driver Note that conceptually there are two different display drivers the virtual driver VDD at the Windows end and the actual driver that does the dirty work e AX 4000h A program calls this function to determine how much work the Windows Virtual Display Driver VDD must do when it switches Windows between the foreground and the background It also tells the VDD to allow the program to have direct access to the video hardware registers e AX 4001h Tells the display driver to save the current video state e AX 4002h
220. been written in another language Note also that a small help window automatically shows you the meaning of each input and output terminal on an icon as you wire it up An icon that has been written in another language is known as a code interface node CIN and because LabView Ill call it LV from now on was originally developed for the Macintosh that platform has the best language support For the PC only Watcom C and Microsoft C C are supported What if you want use your own brand of assembler or any assembler for that matter There is a way LabView can call any dynamic link library DLL function Sun workstations and Macintoshes also have the equivalent to the DLL mechanism This is great as you can put all your hardware dependent low level code into a DLL and write a version for each platform the rest of LabView will automatically work on any of the platforms A standard skeleton DLL written in assembly language is on the Companion disk in directory LV DLL To find out more about LabView National Instruments has a Web page at http www natinst com Layout Programming There is another easy way to generate a DLL its name is Layout Layout is another VPL Comparing Layout with LabView is like comparing chalk and cheese but there is a method in my madness Layout had its origins on DOS and Layout for DOS still exists Layout for Windows made its appearance in the world in November 1994 Lay
221. bel cannot start with O 9 LDT What this service does is create an entry in your application Local Descriptor Table and returns the index to that entry that is the selector The way selectors work is that you can treat them just like the old segment values Something like mov ax Bo00selector mov eS ax mov bx O mov es bx x Linear This code will write the ASCII character x directly to the address video RAM at address B000 0000 From the theory in Chapter 1 that will be a physical and or linear address of 000B0000h I made the complete linear physical address up to 32 bits since thats Jte DPMI specification places a few caveats upon the0002 function The descriptor s limit will be set to 64K Multiple calls to this function with the same segment address will return the same selector Descriptors created by this function can never be modified or freed For this reason the function should be used sparingly Clients which need to examine various Real mode addresses using the same selector should allocate a descriptor with INT 3 1h AX 0000h and change the base address in the descriptor as necessary using function 0007h 2 Note that all WinApps share a single LDT The system VM maintains one each LDT GDT and IDT 3 Notice above that I used the word linear address This is explained in Chapter Basically in NOW the same thing but using a Windows function Saving and restorin
222. ble and link I ve listed them here for your convenience Note that the Make file is designed for Microsofts NMAKE EXE but you should be able to get it going with other Make programs I prefer NMAKE even for making Borland code What follows is particular to TASM Look at the previous chapter for specifics on RC DEF and MAK files for Microsoft This is the WINHULLO RC file in SKELETN2 Nothing new here these arbitrary equates could have been in an Include ile define IDM_QUIT 200 124 Windows Assembly Language amp Systems Programming define IDM_ABOUT 20T winhullo MENU BEGIN POPUP Pile BEGIN MENUITEM Quit IDM_QUIT MENUITEM About IDM ABOUT END END DEF file Now for the definition file NAME WINHULLO DESCRIPTION Demo ASM hullo program EXETYPE WINDOWS STUB WINSTUB EXE CODE PRELOAD MOVEABLE DATA PRELOAD MOVEABLE MULTIPLE HEAPSIZE 1024 STACKSIZE 8192 EXPORTS WINHULLOPROC Note that some LINK programs are case sensitive and some are not Borlands TLINK EXE prior to version 2 0 is not while version 2 0 onwards is This did create some problems for me when upgrading One problem I found was that the line name WINHULLO in the DEF file had to be in capitals Borland I have designed the WINHULLO MAK file for Borlands TASM Make file and TLINK to be comprehensive and well documented NOTE this Make file has been modified for Borland C to be used with TA
223. bler is smart enough to know from the EXTRN functionname FAR declarations that the call should be FAR The override could be put in but for the programmer information only S0 what about the PASCAL qualifier The choices here are nothing PASCAL C BASIC FORTRAN STDCALL or PROLOG The qualifiers available vary with different assemblers Normally a CALL instruction just pushes the return address on to the stack and the RET at the end of the called procedure pops it off The PASCAL qualifer will cause the parameters to push on in the correct order and will also remove them assembling a RET number at the end of the procedure as discussed above and on page 107 We require the PASCAL qualifier to call Windows functions We would use the C qualifier to call C functions perhaps some third party C library we want to use The effect is the same but the parameters are pushed on in the reverse order and not removed by the called routine they are removed from the stack after execution returns from the procedure Whatever language we are calling the result is that the high level CALL instruction assembles with all of the pushes pops and other stack manipulations generated automatically unassemble such code and you will see something like the program of the previous chapter This is the main message loop mainloop lea ax s2 High Level Assembly 117 call TRANSLATEMESSAGE PASCAL 8Ss ax lea ax s2 ll DISPA
224. can grow downward in memory without interfering with the parameters or the intermediate area that is to be used for temporary data In Figure 4 1 increasing addresses are downward Note that the return address is not FAR but NEAR as WINMAIN is called by the startup code within the same segment not directly from Windows Note that the old value of BP is saved on the stack Note that lpCmdLine is a 32 bit value and so occupies four memory locations for explanation of label prefixes refer to page 82 The first instance of the program has to create a window class data structure and call RegisterClass It determined this by testing hPreviInstance which is zero if this is the first instance Note that the handle for this particular instance is hInstance ALL OF THIS STUFF DOWN TO CREATEWIN IS PRETTY HORRIBLE SO LET YOUR EYES GLAZE OVER AND READ QUICKLY ONWARD TO CREATEWIN mov mov mov sub mov mov mov mov sub push mov sub push push call mov sub push mov WORD PTR bp 46 3 wndclass WORD PTR bp 44 OFFSET SKELETONPROC addr of callback WORD PTR bp 42 SEG SKELETONPROC ax WOR function for window ax D PTR bp 40 ax WORD PTR bp 38 ax ax WORD PTR bp 12 hInstance word PTR bp 36 ax ax ax snull use Windows default icons ax 1 cx IDI_APPLICATION Default application icon dx dx i dx cx F LOADICON WORD PTR bp 34 ax ax ax null use Window
225. can have a data area that a Windows program can get at but there are certain extra considerations If the TSR is being copied to each V86 machine as it is created won t each have its own code and data Therefore if a Windows program looks in the IVT to access the DOS TSR which one will it see Will it just see the copy in the system VM Yes the WinApp will only see the IVT in the system VM and hence the TSR in the system VM but Microsoft arranged things so that the subsequent copies of the TSR are not really copies as such they all map back to the one physical TSR So there only appear to be multiple copies of the TSR Thus the TSR is truly global I have elaborated upon this point with a supporting figure on page 343 There is still another major problem Yes the WinApp can get at the DOS TSR but what if a DOSApp in a VM via the TSR or whatever method wants to asynchronously send a message to a WinApp in the system VM I talked about signalling between applications back in Chapter 10 but that was between WinApps Getting a DOSApp to signal a WinApp across VMs is a new ball game Signalling a WinApp from a DOSApp A DOS TSR can be made to appear in all virtual machines or only in the system VM so it is a ready means of providing the signalling t You can verify this by running COMMAND COM in two different windows Run the DOS MEM program to see where the DOS TSR is located then go into DEBUG COM and du
226. cause Windows 3 x and 95 only support v0 9 For further information refer to the above source the body of this book and the Companion Disk The complete specification is also on line at http www delorie com djgpp doc This Appendix is in two portions first a listing of all services grouped functionally and second a detail description of all v0 9 functions DPMI INT 31h Functions Listed by Functional Group Function Function DPMI Number Name 0 9 1 0 LDT MANAGEMENT SERVICES 0000h Allocate LDT Descriptor 0001h Free LDT Descriptor 0002h Map Real mode Segment to Descriptor 0003h Get Selector Increment Value 0006h Get Segment Base Address x xX X x 385 386 Windows Assembly Language amp Systems Programming Function Function DPMI 0 p Number Name 0007h Set Segment Base Address 0008h Set Segment Limit 0009h Set Descriptor Access Rights 000Ah Create Alias Descriptor 000Bh Get Descriptor 000Ch Set Descriptor 000Dh Allocate Specific LDT Descriptor QOOEh Get Multiple Descriptors 000Fh Set Multiple Descriptors EXTENDED MEMORY MANAGEMENT SERVICES 0500h Get Free Memory Information 0501h Allocate Memory Block 0502h Free Memory Block 0503h Resize Memory Block 0504h Allocate Linear Memory Block 0505h Resize Linear Memory Block 0506h Get Page Attributes 0507h Set Page Attributes 0508h Map Device in Memory Block 0509h Map Conventional Memory in Memory Block 050Ah Get Mem
227. ccepts the same syntax for the high level procedures though it does not support ADDR and isnt needed in 32 bit programming and ADDR can be replaced by OFFSET for static data You will notice that I have used correct case in all symbols I used the m1 switch to turn on case sensitivity which is a break from my past I decided to invoke case sensitivity for all true 32 bit code which is why I have shown correct case for all the 32 bit API functions Support Files There is nothing much to say about resource tiles They work the same as before 32 bit Ring 3 315 W32DEMO RC resource file these arbitrary equates could have been in an include file define IDM QUIT 100 define IDM_ABOUT 101 ICON 1 ICON GOOFEE ico W32DEMO MENU BEGIN POPUP File BEGIN MENUITEM Quit IDM QUIT MENUITEM About IDM_ABOUT END END The program BRC32 EXE is required to compile a RC file to RES Make file Now may be the best place to show the Make file MAKEFILE W32DEMO Win32 demo application TASM32 EXE TLINK32 EXE BRC32 EXE MAKE EXE are from TASM v5 0 Make sure the path points to them Path only needs to point to bin subdirectory TLINK32 finds IMPORT32 LIB in the lib subdirectory ok You should be in a DOS box by executing the PIF file B32TOOLS PIF make a shortcut on your desktop TLINK32 switches Tpa build 32 bit EXE aa target Windows 32 bit application v include
228. ce e eee eee ene renee 132 6 Program Design 137 Preamble eoek ides Reeve E er en sae ey Meow 137 Object Addressing 0 6s sen cee bd eevee renee eee eee 138 Calling a Function csceccceecenseseeteereeees 138 Barly Bingin sesia nann tat etens eas Cie ses tee teksts 14 Late Binding f ieacansinesseeeiewseanse eas sonnets 142 C Binding i006 ing602 tenia a sneer ees 142 Ch 7 8 vi Page Assembly Language Binding s esssssssesrrrsresre 145 Use of THIS sass segs eebee aranne n renie EE pAs aa 145 Interfacing with C ssesssrsrerrssseronrsrrerrererer 147 Compiling to ASM O P ssssssssssrerereseresesesre 147 In Line Assembly eceeeeer erence renee en eeeee 148 In Line Dos and Don ts eee ee eee eee eee nets 149 ThesASM Stibtanieestetaieiewrcotenesaeaenstdanerrey 150 Compile and Assemble Steps sese seer eeeeenes 151 The Amazing 9 Line Program s sssseseeseereerrrerere 153 A Skeleton Program s sseserereresrrereererereereree 154 Ovoide s eaaa aa aaa E aE AE 156 E E E E EE A PE P ak eee ees 157 Messaze Handling issn cthicathirndanwecpiiensius tes 7 The WINDOW Object s sssseseerererrsereserereree 158 WINMAIN eeeeeesterssseeerrersrrrerreerrrreerreeees 162 Callback osae wie s canna abase Pes ements ae an e 165 MIE Gy settee Sneed et stehaeaebinteal eh 168 Taher iaee aud cctv ado gerladoueed Gado TAANS 171 Getting it Together sssesorserrereererrsrresreress 175 Postamble sux
229. chain de scribed in Chapter 11 di ipl ax Z di cs1 ax j di flagsl ax S di sp1 6 to original vector by putting it into callback data structure mov ax cs segmentrealint mov es di csl ax mov es di ipl ax i mov ax cs offsetrealint l i iret installint ENDP e e e a ay Separate ISRs for IVT andJDJ Note that there are two ISRs one each for interrupts that come via the IDT and those that get reflected up from Real mode via the IVT With regard to the installation of these ISRs note that I did not hook the vectors as soon as the WinApp received the WM CREATE message as this can under certain circumstances impair the display of the window Instead I posted a message WM_USER 1 which at a later stage calls the install code see the complete program on the Companion Disk in WIN2REAL and further development in REAL2WIN With regard to exiting from the program I did of course unhook the vectors upon receipt of a WM_ DESTROY message VMs have preemptive time slicing by the DPMI host ISR reentrancy Reference source The case of the missing code segment DOS Win Transitions 323 Problems Issues with the Protected Mode ISRs POSTMESSAGE will work for both ISRs when Windows is loaded in Enhanced mode Even when running a DOS application POSTMESSAGE will send the WM_USER message to the window immediately In this example code t
230. cially the WINDOWS qualifier Curiously Microsoft has only gone partway along that road with an extended PROC very much like TASM s but no WINDOWS qualifier Microsoft doesnt have an extended CALL either but has opted for something else called INVOKE which is really an extended call MASM v6 x s MASM6 s lack of a WINDOWS qualifier for PROC means that declaring a callback PROC becomes an absolute pain Rather than resort to CMACROS INC and PROLOGUE INC to insert the required prolog and epilog code how much simpler it would have been if Microsoft had thought ahead just that little bit further There is a mechanism using OPTION PROLOGUE and OPTION EPILOGUE directives to overrride the default prolog and epilog and there is a method for suppressing default prolog and epilog as well as a method for restoring the default MASM6 skeleton program INVOKE high level call High Level Assembly 127 The issue of prolog and epilog have become more streamlined with 32 bit applications requiring only the STDCALL qualifier see page 78 Anyway I guess we have to go with the flow so the 16 bit skeleton program on the Companion Disk in directory ASMDEMO2 and listed at the end of this chapter uses CMACROS INC Note that you cant see it explicitly included in the listing as that is done indirectly by the WINDOWS INC tile The Companion Disk also has a similar program in ASMDEMO1 which has the startup code in the
231. clslpszmenuname mov di ax mov d i 2 ds Oh and make sure that your callback procedure name is all capital letters High Level Assembly 131 Label scope Another major difference is in the scope of labels I have covered differences that topic beginning on page 120 This is one aspect of MASM6 s move toward the code integrity we expect from a high level compiler Prototyping is another I think that many serious programmers will choose MASM on this basis and it is an area where Borland had to play catch up withTASMS Which one All of these comments are of course my personal opinion not the final truth engraved in stone and I suggest that potential buyers consider most carefully what features are most important Have a look at reviews in magazines If OOP is your thing then look closely at TASM Do bear in mind that my comments are based upon particular versions and even maintenance releases of the Same version number can have significant improvements Therefore take all of the above comments with a pinch of salt and check out the features for yourself before buying One interesting point is that MASM6 comes with Programmer s Workbench PWB an editor and IDE as well as CodeView debugger Borland does not provide an editor or IDE but the Turbo Debugger is very nice I have made some further comments on this on page 309 MASM Assembling and Linking Resource compiling and linking are as per Chapter 4 though yo
232. ction is sometimes used to test individual bits since it can be followed by JC Jump on Carry set or JNC Jump on Carry not set 56 Windows Assembly Language amp Systems Programming A limit with the 8088 8086 is that the count operand can only be a value of 1 if in immediate mode as shown in Figure 2 7 If the shift is to be more than bit a count value must first be moved into CL mov cl 3 shr al cl shift 3 bits right SAR ROL ROR RCR RCL Note that the shift operations can also be on 16 bit and 32 bit registers SHL does exactly the opposite of SHR moving zeros into the LSB and the MSB out to the carry flag SAR Shift Arithmetic Right works like SHR except it maintains the sign This is most useful for signed numbers Refer to Figure 2T ROL Rotate Left and ROR Rotate Right work similarly to the shift instructions except what falls out is rotated around back in the other end Refer to Figure 2 7 Thus the contents are never lost but circulate around the register ROL is the mirror image of ROR sending the MSB to the carry flag and back around to the LSB RCR Rotate through Carry Right and RCL work as per ROR and ROL except the path of the bits goes through the carry flag See Figure 2 7 Code and Data Labels Labels are potentially an area of enormous confusion so I review them here very carefully Labels can be used to mark a place in the code or to name some data They are i
233. cursorname aoe 32 VIRTUAL hbrbackground WORD COLOR_BACKGROUND VIRTUAL szclassname BYTE 32 0 VIRTUAL sztitlename BYTE 32 0 VIRTUAL hmenu WORD 0 VIRTUAL hwndparent WORD 0 VIRTUAL wheight WORD 200 VIRTUAL wwidth WORD 250 Program Design 159 VIRTUAL y_coord WORD 0 VIRTUAL x coord WORD ad VIRTUAL createstvlelo WORD VIRTUAL createstylehi WORD WS _OVERLAPPEDWINDOW VIRTUAL hfont WORD This doesnf look like any structure definition youve seen before Instead of using STRUC I have used TASM s TABLE directive which has some advantages but a different syntax 00 The Borland programmers will probably gag when they see how I limitations have used their TABLE directive but I found it useful to define of STRUC both data and procedures I wanted to retain a program that would work with other non 00 assemblers with only minimal change The above TABLE can be replaced with the conventional STRUC but the latter has disadvantages the two most glaring being e it cannot initialise fields with forward references and initializing fields of instances is rigid and awkward However it can be done check out Object Oriented Programming in Assembly Language by R L Hyde Dr Dobb s Journal March 1990 p 66 73 110 I 11 The TABLE directive only exists with TASM version 3 0 not before I have only bitten off a little bit of the new TASM s 00 capability however my end result is quite simple and elega
234. d on reading the MASM manuals particularly Quick assembler version 2 01 This version supports high level PROCs and the LOCAL directive as discussed in this book Quick C with Quick assembler supports Windows development MASM introduced local scoping of labels by default and looking back through my manuals I see that v5 1 defined all labels as global so the concept came in after that Version 5 1 has global code labels only but local to the module a module being a source tile that will be linked with others TASM v3 0 s VERSION directive claims to be able to emulate MASM versions 4 0 5 0 5 1 and 5 2 Incidentally MASM version 5 2 appears to be equivalent to Quick assembler version 2 0 1 TASM s TASM s native mode is a bit different if you want a label to have scope only within the current procedure prefix it with and put the LOCALS directive right at the beginning of the file This holds true for code labels and all labels defined by high level PROCs and LOCAL directives 122 Windows Assembly Language amp Systems Programming LOCAL directive So what about TASM s default treatment of labels as global Quite frankly it s a nuisance Let me quote the TASM v3 0 manual All argument names specified in the procedure header whether ARGs passed arguments RETURNS return arguments or LOCAL s local variables are global in scope unless you give them names prepended with the local symbol prefix
235. d Destination Index CMPSB These instructions compare bytes or words pointed to by ES DI CMPSW and DS SI and set flags for use by J condition instructions For example to use CMPSB with REP mov cx str_length rep cmpsb jnz ditferen ce fnd This example will compare the two strings until the end of the string set by value in CX OR until a non equal comparison is reached in which case CX will point to the position in the string at which the difference was found and the zero flag will be clear SCASB Use these instructions to compare AL or AX with the value SCASW pointed to by ES DI Note they are most often used with REPNE A typical use is setun DS to beginning of PSP will be for COM files amp at start of EXE prog else use ES override mov al mov di 080h length of tail in PSP mov cx di could use override mov di 08ih command tail in PSP we will assume that ES is set to the start of the PSP should be for EXE amp COM files REPNE SCASB jcxz no slash yes slash was found mov al di scould use override 50 Windows Assembly Language amp Systems Programming Command line tail LODSB LODSW STOSB STOSW The code searches the DOS command tail in the PSP see Figure 1 8 to see if there is a switch followed by a letter If the loop terminates without finding a slash CX will equal zero so the special conditional jump instruction JCXZ which tests if CX 0 can be u
236. d Enhanced modes With Standard mode the question Real Mode Access 279 of VMs doesn t arise This means that all access to the IVT from a WinApp is to the actual original real physical bona fide IVT That s not the problem in fact that s good because there s no need to jump VMs However Windows itself is in a strange state while a DOSApp is running I have elaborated more upon this in Chapter 12 Both Enhanced and Standard modes however can use the same mechanism for transferring up to Protected mode Installing a There is a DPMI service that allows us to hook from a WinApp a Real to vector in the IVT function 0201h Set Real Mode Interrupt Protected Vector and another that will redirect it up to Protected mode mode function 0303h Allocate Real Mode Callback Address handler Actually 0303h is called first followed by 0201h Get the picture here an interrupt occurs while the CPU is in Real mode but the vector is to a DPMI routine that switches the CPU to Protected mode and passes control up to a WinApp The above may seem like a suitable method for a DOSApp to communicate with a WinApp but executing 0303h and 0201h from the WinApp will only hook the vector in the IVT of the system VM in the case of Enhanced mode However in Standard mode there s only one IVT anyway so in theory this method works The obvious point here is that if Windows is loaded in Enhanced mode then as well as
237. d integer multiply OF ACE IN accum 8 imm IN Accum DX Input from port DX port None INC mem INC reg Increment OF SF ZF AF PE INS rep deststr DX INS deststr DX Input string None INT 8 imm Interrupt IF 0 trap 0 INTO Interrupt on overflow IF 0 trap IRET Interrupt return All JMP 16 memptr JMP 16 regptr JMP 32 memptr JMP far JMP near JMP short Unconditional jump None Jxxx short Conditional jump None LAHF Load AH with flags LO byte flags None LAR Load access rights byte ZF LDS 16 reg 32 mem Load pointer to DS reg None 372 Windows Assembly Language amp Systems Programming Format Instruction Description ESE Flags affected 86 286 386 LEA 16 reg 16 mem Load effective address to register None LEAVE Leave procedure None LES 16 reg 32 mem Load pointer to ES reg None LFS Load pointer to FS reg None LGDT None LGS Load pointer to GS None LIDT Load IF descriptor table None LLDT None LMSW Load machine status word None LOCK Bus lock prefix None LODS rep sourcestr None LODS sourcestr Load byte word dword None LOOP short Load global descriptor table Load local descriptor table Repeat load byte word dword Loop None LOOPE LOOPZ short Loop equal zoom None LOOPNE LOOPNZ short Loop while not equal not Zero None LSL Load segment limit LE LSS Load pointer to
238. d you will be able to see exactly the traffic on INT 2Fh at all times What I found most fascinating is that once Windows has loaded the traffic is continuous The implication here is that you have a mechanism for Windows to continuously wake up a TSR Writing Windows Aware DOSApps If you are writing a DOS application that is going to make use of extended memory there are plenty of tools available and some compilers automatically take care of this for you Thus the old 1M limit is history The extended memory that your program will use is still within the same VM as the V86 VM Switching into Protected mode from Real mode to run code in Protected mode and hence above 1M in no way conflicts with the WinApps since they are in the system VM Also your VM has its own LDT and IVT so you can hook vectors to your hearts content 350 Windows Assembly Language amp Systems Programming INT 2Fh versus INT 31h GOOFEE EXE There is a lot to be said for writing DOS programs that are designed to run under Windows and quite likely this area of development will remain alive You should remember that the DPMI INT 3 1 h functions are only available when the CPU is in Protected mode not while it is in V86 mode However the INT 2Fh extensions are available in V86 Enhanced Real mode and Standard Real mode Also dont forget that V86 and Protected mode overlap so you can readily address all of the first 1M of the VM from Protected mode
239. d you will see RINGOCALLGATE which is the pointer that is called to get to the ring 0 code Actually RINGOCALLGATE is an alias to ring0_cs ring0_ off So the instruction call RINGOCALLGATE will call the ring 0 code What does the ring 0 code look like Here is the listing for HEAVEN ASM this file is named HEAVEN ASM as it s as hish as we can masm is stupid this ese has to be a separate to generate 32 bit co without the 66 prefix jfile PUBLIC RINGOFUNC TEXT2 SEGMENT DWORD PUBLIC USE32 CODE ASSUME CS _TEXT2 RINGOFUNC PROC FAR TELE NOTE must remove any params passed by callgate RINGOFUNC ENDP _TEXT2 ENDS END This example is doing absolutely nothing just returning You will know that it works if you don t get a general protection error message Structure Note that I did not use mMopEL in this file because it would of ring 0 create a code segment with the name TEXT and the 386p segment atthe very beginning ofthe file ifpreceeding MODEL SMALL would cause a 32 bit code segment The linker would give the error message that two segments with the same name _ TEXT cannot be combined if one is 16 bit and the other 32 bit Combining It s pretty stupid but we are able to combine 16 bit and 32 bit 16 amp segments by giving them different names and placing them in the 32 bit same class The TEXT segment in ASMRINGO ASM has class segments CODE so putting copz at the end of the SEGME
240. ddress region is above 1MB boundary Int 31 h Function 0603h Relock Real Mode Region Relocks a memory region that was previously declared as pageable with the Mark Real Mode Region as Pageable function Int 31 h Function 0602h Call with AX 0603h BX CX starting linear address of memory to relock SI DI size of region to relock bytes Returns if function successful CF clear if function unsuccessful CF set AX error code 398 Windows Assembly Language amp Systems Programming FORMAT Heading Description Retums 8002h invalid state region not marked as pageable 8013h physical memory unavailable 8025h invalid linear address region is above 1 MB boundary Int 31h Function 0604h Get Page Size Returns the size of a single memory page in bytes Call with AX 0604h Returns if function successful CF clear BX CX page size in bytes if function unsuccessful set AX error code 8001 h unsupported function 16 bit host Int 31h Function 0702h Mark Page as Demand Paging Candidate Notifies the DPMI host that a range of pages may be placed at the head of the page out candidate list forcing these pages to be replaced ahead of other pages even if the memory has been accessed recently The contents of the pages will be preserved Call with AX 0702h BX CX starting linear address of pages to mark as paging candidates SEDI size of region to mark bytes Ret
241. debug info TASM32 switches Zi include debug info the last parameter is the resource file to be bound to the executable the 2nd last param is the definition file make B Will build EXE make B DDEBUG Will build the debug version FN W32DEMO opgs FN obj DEF FN def if d DEBUG TASMDEBUG zi LNKDBG v telse TASMDEBUG LNKDBG lendif 316 Windows Assembly Language amp Systems Programming if d MAKEDIR IMP MAKEDIR lib import32 else IMP import32 lendif FN EXE OBJS DEF tlink32 Tpe aa c LNKDBG OBJS FN IMP DEF FN asm obj tasm32 TASMDEBUG ml amp asm brc32 r FN re In the above Make file you can see the invocation of BRC32 EXE It is used with a r switch to mean compile only which is probably optional Binding In earlier examples I have run RC EXE again after LINK to bind resources the RES file to the EXE tile However TLINK32 does this to the automatically if the name of the RES file is appended onto the end executable of the command line The last FN achieves this Compatibility I have a lot of trouble with Borland Make tiles Although there is of Borland amp a switch for setting compatibility with Microsofts NMAKE EXE Microsoft it is still not compatible I have never been able to get a Make file Make files I have created for NMAKE to work with Borlands MARE I have to resort to taking an example Ma
242. dent mechanism for accessing the PCI chips One point to be careful about however is that not all BIOSs implement the new specification fully or maybe they may not have implemented the latest version of the specification 2 1 at time of writing Of particular interest is that version 2 1 specifies entry points for Real mode 16 bit Protected mode and 32 bit Protected mode The 386 and later CPUs can operate in 16 bit Protected mode which is what Windows 3 x applications run in and they can also operate in 32 bit Protected mode which is what native Windows NT and Windows 95 applications run in A further source of information about this is PCI System Architecture third edition by Tom Shanley and Don Anderson Addison Wesley USA 1995 The normal BIOS that we have considered so far in this book is designed at least originally for an 8088 CPU which only runs in Real mode In a nutshell Real mode uses the now familiar segment offset form of addressing which has a 1M upper limit The 286 and 386 CPUs are able to operate in Protected mode which uses a different addressing mechanism and is able to address extended memory beyond 1M as explained in Chapter 1 One of the greatest criticisms of Windows 3 x is its reliance on DOS and BIOS to call any of these software interrupts the CPU must switch back into Real mode which takes time Real mode PC Hardware 93 It is possible to write code that can execute
243. dle of control window hi word of lparam has notification code jne notbutton Direct Hardware Access 241 lea si controli since Qi points to windowl call DESTROYWINDOW PASCAL si hwnd kill the button mov si hwnd 0O must clear hwnd if want to makeO later what we will do now is make the new window always stay visible lea si windowl call SETTIMER PASCAL si hwnd 1 200 0 0 l timer id post WM_TIMER to window every 200mS notbutton ret szmsg DB Created by Barry Kauler 1992 0 szhdg DB Message Box 0 wichar let s bring back the button if any key pressed lea si controll Since si points to windowl call si make PASCAL si ret e call KILLTIMER PASCAL si hwnd 1 kill the timer call POSTQUITMESSAGE PASCAL 0 normal exit ret er comes this way if a WM TIMER message this WinApp keeps on posting a WM_ TIMER message to itself thus this section is in a continuous loop call dpmidemo ret eee ETEA E TO ie A AGB he neater ae a A aa ee Be we en comes here if button selected now we will do some direct video sales ah ae i Note that this only works for o Or vedo standard VGA Modification is gt al mode ah width bh page required for SVGA see mov mode al save DPMI0O README TXT on mov columns ah the Companion Disk mov vpage bh mov ah 3 get current cursor position mov oo eee video page int gt dh row dl col cx cur size mov a be dx save zall of
244. do such things as allocate memory modify descriptors and call Real mode software using segment offset addressing and running within the 1M limit 198 Windows Assembly Language amp Systems Programming DPMI 9 and 1 0 Windows 3 0 running in 386 Enhanced mode supports DPMI version 0 9 Windows 3 0 running in Standard mode supports a subset of DPMI that enables applications to call TSR programs and device drivers running in real or virtual 86 mode Windows applications should call only the following AX values for DPMI version 0 9 functions 0200h 0201h 0300h 0302h 0303h 0304h 0305h Windows applications should not use DPMI s MS DOS memory management functions The Windows 3 0 Kernel has two functions GlobalDOSAIlocQ and GlobalDOSFree that should be used by Windows applications and DLL for allocating and freeing MS DOS addressable memory Other than those listed above no DPMI functions are required for Windows applications since the Kernel provides functions for allocating memory manipulating descriptors and locking memory Non Windows applications running in 386 Enhanced mode can use all the DPMI version 0 9 functions since they are not restricted by the Kernel However to throw a spanner into the works Microsoft has this in documentation supplied with the SDK v3 1 Windows 3 0 and later in 386 Enhanced mode supports DPMI version 1 0 Windows 3 0 and later in Standard mode supports a subset
245. dow registers 26 Shift instructions 55 SHORT addressing mode 42 SHOWWINDOW 101 157 Signed number 7 Signed number compare 44 51 Size override 290 SMALL model 111 Software interrupts 373 Source files needed Windows program 89 Stack concept of 39 Stack instructions 38 STACKTRACECSIPFIRSTO 214 STACKTRACEFIRST 214 STACKTRACENEXT 214 STDCALL calling convention 78 STI instruction 31 245 STOSx instructions 50 String instructions 47 STRUC amp ENDS directives 65 114 STRUC assembler differences 130 STRUC 00 limitations of 159 Structures 65 SUB instruction 52 Subclassing with override 00 program 143 Super VGA 242 System driver functions 217 SYSTEM INI 5 288 SYSTEMHEAPINFO 214 T TABLE directive 158 Task State Segment TSS 32 TASKFINDHANDLE 214 TASKFIRSTQ 214 TASKGETCSIPQ 214 TASKNEXT 214 TASKSETCSIPQ 214 TASKSWITCH 214 TASM version 2 x 87 TASM vesion 3 0 125 TASM3 versus MASM6 125 TASMS installing 309 TASMS skeleton program 310 TASMS versus MASM6 308 TDUMP EXE 235 TERMINATEAPP 214 TEST instruction 54 Text mode direct video 233 Text mode running the screen in 230 Text mode Windows applications 227 TEXTEQU 130 TEXTOUT 105 119 THIS 145 Thread32First 215 Thread32Next 215 Threads 223 THROW 212 Thunking 219 TIMERCOUNT 214 Timers 247 TLINK EXE 124 TOOLHELP DLL 199 213 254 Toolhelp32readProcessMemory 215 Transfer of control 39 TRANSLATEMESSAGEO 79 TSR 250 TSR DOS 251 273 TSR DOS l
246. dows jne giveitanothergo jmp dorego giveitanothergo cmp ax 1687h je go2F otherwise will get in endless loop cmp CS dpmi loaded 0 ams go2F for all other cases exit DOS Win Transitions 339 after Windows has loaded if we want to hook the IDT Fs need to test if ok cmp cs winloaded 0 a problem exits what if come here before the idt f properly setup pusha mov ax 1687h test for dpmi host int 2Fh cmp ax 0 ax 0 if dpmi host present Jne exitd mov cs dpmiloaded 1 exit5 popa go2f jmp DWORD PTR cs oldoffivt2F Cs return a pointer to the TSR structure mov WORD PTR cs TSR Info TSR Next di mov WORD PTR cs TSR_Info TSR_Next 2 es push cs pop es mov di OFFSET TSR Info this chains the tsr data jmp go2ft structures Reference The TSR data structure is particularly interesting because it sources allows you to pass various information about your TSR to Windows see Appendix D Also for Microsoft Developer Network MSDN members the January 1997 set of CD ROMs has further information on this topic in the Archive Library CD ROM You can control whether your TSR is instantiated in each VM or not The default is not which means that every VM maps back to the same TSR In most cases this is highly desirable including our case of a global data area in the TSR i Getting it Together Testing the TSR2WIN directory on your version of the Companion Disk may programs co
247. e 0303h Allocate Real Mode Callback Address 0304h Free Real Mode Callback Address 0305h Get State Save Restore Addresses 0306h Get Raw CPU Mode Switch Addresses x k k He F k PAGF MANAGEMENT SERVICES 0600h Lock Linear Region 0601h Unlock Linear Region 0602h Mark Real Mode Region as Pageable 0603h Relock Real Mode Region 0604h Get Page Size 0702h Mark Page as Demand Paging Candidate 0703h Discard Page Contents amp amp amp KF OF EF FF KF EF OF DEBUG SUPPORT SERVICES 0B00h Set Debug Watchpoint OBO 1h Clear Debug Watchpoint 0B02h Get State of Debug Watchpoint 0B03h Reset Debug Watchpoint X 388 Windows Assembly Language amp Systems Programming Function Function DPMI Number Name 0 9 1 0 MISCELLANEOUS SERVICES 0400h Get DPMI Version 0401h Get DPMI Capabilities 0A00h Get Vendor Specific API Entry Point i 0CO00h Install Resident Service Provider Callback 0COlh Terminate and Stay Resident QEOOh Get Coprocessor Status QEOlh Set Coprocessor Emulation F F KF F DPMI Services Detail Int 2Fh Function 1686h Get CPU Mode Returns information about the current CPU mode Programs which only execute in Protected mode do not need to call this function Call with AX 1686h Returns if executing in Protected mode AX 0 if executing in Real mode or Virtual 86 mode AX nonzero Int 2Fh Function 1687h Obtain Real to Protected Mode Switch En
248. e 1M conventional memory limit for Real mode Of course Real and virtual 86 modes have paragraph addresses in the segment registers so these can only reference the first 1M however you are quite at liberty to use offsets to access code and data beyond 1M A bit of setting up is required to use Real and virtual 86 modes in this way and I recommend a good book Al Williams has worked it all out and has an entire chapter dedicated to this in his book DOSS A Developer s Guide Advanced Programming Guide to DOS M amp T Publishing Inc USA 1991 There is probably a more recent version of the book probably with a new title but the chapter on 32 bit programming is still quite relevant even in the 1991 book Ring Transition Mechanism Say that for whatever reason you want your program to have the unrestricted access and the total control of ring zero Unfortunately your program will be executing in ring 3 segments which means that if you try to do an I O operation such as use the IN and OUT instructions there will be a CPU exception And if 292 Windows Assembly Language amp Systems Programming Interrupt gate Call gate we want to hook an interrupt we will be doing so at the asse end of the animal What if we want to call some of the powerful functions in the Windows kernel and in virtual device drivers Sorry but even if you knew how to address them you d get a CPU exception because they are ring 0 segments
249. e AX 1680h e AX 1686h e AX 1687h AX 168Ah Release current virtual machine time slice Get CPU mode Return Real to Protected mode switch entry point Get vendor specific API entry point Apart from these functions DOS has a lot of other functions under INT 2Fh Other software products provide enhancements to INT 2Fh Windows provides extra services for device driver development discussed a bit further on and the new specification for FAX and modem communication adds further functions INT 2Fh is a mixture of all sorts of stuff INT 3 lh has these major groups of services Extended memory management services Works with blocks of linear memory abovelM and deals with linear addresses refer back to pages 28 These services allocate and release memory but you still have the problem of accessing it for which you need a descriptor for that you need the descriptor management services e LDT descriptor management services These allocate modify inspect and deallocate descriptors in the applications Local Descriptor Table LDT e Page management services These will only work on a system with paging They are used for locking and unlocking pages in memory e Interrupt management services These allow Protected mode applications to intercept Real mode interrupts and hook processor exceptions Some also enable cooperation with the DPMI host in maintaining a virtual interrupt flag for the application e Transl
250. e EFLAGS 32 bit SF sign flag 386 TF trap flag IF interrupt enable DF direction flaa OF overflow IopL I o privilege level 286 386 only NT nested tank flag RF resume flag 386 only VM virtual 86 mode IOPL field The field of immediate interest to us is IOPL which means Input Output Privilege Level Referring back to page 3 1 privilege level varies from 0 to 3 with O being most privileged IOPL is set by the operating system and an application must have a privilege level at least as privileged as IOPL for it to be allowed to perform T O With Windows the IOPL is set to 0 while applications and DLLs run down at 3 so it appears that they cant do I O But this is only how it appears for the protection mechanism is only used by Windows as a control mechanism and in some cases I O is allowed clarification is needed here WO and related instructions CLI STI PUSHF POPF 1 0 exception handler Windows 95 VO Direct Hardware Access 245 First however we should be clear about what we mean by allowing I O Hardware interrupts are of course part of I O as is control of the interrupt flag IF IF is a mask that determines whether external interrupts are allowed to occur It is O if interrupts are disabled and 1 if enabled There are two instructions that control this flag CLI meaning CLear Interrupt and STI meaning SeT Interrupt There is another means of control
251. e Ptr is nonzero is passed to the virtual device when it is initialized The member can contain any value and often contains a pointer to some device specific structure SIS Instance Data_Ptr Points to a list of data to be instanced that is allocated uniquely for each new virtual machine If the member is zero then no data is instanced Each entry in the list is an Instance _Item_Struc structure The list is terminated with a 32 bit zero SIS_Opt_Instance_Data_Ptr Points to a list of data to be optionally instanced Available only if SIS_Version is 4 0 Instance_Item_Struc Instance_Item_Struc STRUC HS_ Ptr dd IIS_ Size dw Instance_Item_Struc ENDS The Instance_Item_Struc structure specifies the starting address and size of a block of instance data Member Description HS_Ptr Points to the starting address of a block of instance data IIS Size Specifies the size in bytes of the block of instance data pointed to by the HS_Ptr member TSR_Info_Struc TSR Info Struc STRUC TSR N amp t dd TSR PSP_ Segment dw TSR_API Ver ID dw 100h TSR_Exec_Flags dw 0 TSR_Exec_Cmd_Show dw 0 TSR_Exec_Cmd_ dd 0 TSR Reserved db 4dup 0 TSR ID Block dd 0 TSR Data_Block dd 0 TSR_ Info _ Struc ENDS 412 Windows Assembly Language amp Systems Programming The TSR_Info_Struc structure has the following fields TSR Next Contains the 32 bit address segment offset of the next TSR_Info_Struc structure in the TSR chain TS
252. e TSR from within Windows or at a DOS prompt inside a VM within Windows the TSR will be inside a virtual machine If the TSR hooks an interrupt vector in the IVT it will only be hooking the vector in the virtual machine Whenever a DOS virtual machine is created Windows copies everything from the actual 1M region into it or rather maps it in The IVT is not the same IVT as the original IVT This is the crux of the problem Perhaps Figure 11 2 will help 274 Windows Assembly Language amp Systems Programming Figure 11 2 A TSR is in a VM The System VM Virtual Machine includes a V86 0 1M real address space and a protected mode running WinApps Video RAM L_BIOS ROM _ The System VM has its own V86 and Protected modes All WinApps DOS virtual machines Real mode access Note that they can even is to this V86 have their own extended machine memory A TSR loaded By loading the TSR before loading Windows for every virtual before machine that Windows creates it will also copy the hooked Windows vector and the TSR Thus by this method you ensure that the TSR appears in is available to all applications every VM Note that I put the word copy in quotes as this is not always to be taken literally See ahead for clarification page 343 Each VM has Note also something most important the descriptor tables The its own LDT system VM will have just one of each LDT and IVT Despite the
253. e Windows program Here is how to go to text mode 7 moy ax 0007h Note that DEATH will have got us to int 10h j the text mode prior to Windows loading A Direct Video Text Mode Routine I ll put it all together I have named this routine directvideo You can call it from wherever in your program you want and modify it as required some suggestions and possibilities follow after the listing If you want to test it you could take one of the earlier programs and perhaps call it from the WM_CHAR case so whenever a key is pushed the routine will execute There is code for this section on the Companion Disk Text mode Here is the listing direct video listing EXTRN GETMODULEHANDLE FAR EXTRN GETPROCADDRESS FAR ee He eH we we Ee DATA dpmiflag DB O 1 dpmi running ok dpmiversion DW 0 jah major al minor mode386flag DB 0 1 386 dpmi type realmodeintsflag DB 0 pul Real mode interr virtualmemflag DB 0 se virt mem support cputype DB 0 2 3 4 286 386 486 Direct Hardware Access 233 BOOOselector DW 0 selector video RAM szmodulename DB USER EXE 0 lprepaintscreen DD 20 Fanta oe see DG are aD ee ae hw nese te ewe w RR ACen CODE directvideo PROC PASCAL NEAR LOCAL winvideomode BYTE USES ax bx cx dx si di call GETMODULEHANDLE PASCAL ds OFFSET szmodulename mov si ax gets a handle for user exe or si si Returns handle in AX jne userexists user exe doesn t exist jmp n
254. e application is loaded and it performs various initialisations before calling the entry point of your program WINMAIN DOS3CALL This code is also the exit point performing the standard INT 21h function 4Ch to exit back to the calling program Look below but dont be mislead by the DOS3CALLO this simply does the same as INT 21h except by a FAR CALL rather than by software interrupt As far as Im aware there is no other difference except that the CALL is faster CODE Here is the startup code start xor bp bp zero bp push bp call INITTASK Initialise the stack Or ax ax jz noinit add cx STACKSLOP Add in stack slop space jc noinit If overflow return error mov hPrev si mov hinst di mov word ptr lpszCmd bx mov word ptr lpszCmd 2 es mov cmdShow dx xor ax ax yy Q gt ax push ax parameter for WAITEVENT call WAITEVENT Clear initial event that started this gt task push hInst parameter for INITAPP call INITAPP Initialise the queue or ax ax jz noinit push hinst params for WINMAIN push hPrev push WORD PTR lpszCmd 2 seg first push WORD PTR lpszcCmd offset second push cmdShow call WINMAIN ix mov ah 4Ch call DOS3CALL Exit with return code from app noinit mov al 0FFh Exit with error code jmp short ix Register initialisation INITTASK The Bare Bones 97 What does the above startup code do There is an explanation in Programmers Reference Volume 1 Overvie
255. e declared in the data segment or in WINDOWSINC This means that the structures declared in WINDOWSINC are also global so instances of them can be made and accessed anywhere So be careful not to use names that conflict with any of those in WINDOWSINC High Level Assembly 121 It is a good move to print out WINDOWSINC for reference In some cases you need to know the names of the fields in a structure or an equate so a printout can be extremely handy WNDCLASS If you look back at pages 113 and 114 youll see how WNDCLASS is used and how it is defined in WINDOWS INC Notice the names of the fields these are different than field names in WINDOWS H In the message structure also shown on the same pages you can see the fields msWPARAM instead of just wParam Dont worry about upper or lower case as traditional assemblers dont care However the ms prefix is there to distinguish this global label I have used WPARAM as a local label within a program although an assembler would complain bitterly if it found a global with the same name Global Although code labels are local to the procedure you can declare override them as global if necessary qlobalplace za global label MASM That s all you need double colons MASM versus TASM Scope Be careful about differences in the scope of labels between MASM and TASM and the various versions of each It is wise to check your particular manual to clarify this The above notes are base
256. e early or late binding When the compiler sees that the call is fixed that is to a particular routine and will not change at run time it optimises and compiles early binding Note that any function that is to be called by late binding must be declared as virtual in the C source code but such a declaration does not mean that the compiler will do so The compiler will compile a call using late binding if the function is virtual and if the call involves THIS as a pointer The call immediately above is an example in which THIS is contained in SI so its value is not actually known at assembly time Therefore late binding is required In my assembly language example I gave windowl and window2 different routines for TEXTOUT Manual optimisation Program Design 145 Assembly Language Binding Binding has been discussed over the previous few pages however further clarification is in order In assembly language we have full control over whether to use early or late binding since we dont have a compiler to make such a decision for us Look back once more to the listing on page 140 The example of a call to textoutmain by early binding the call immediately after the LEA instruction is ok because SI will always be the same when execution reaches the CALL instruction However what if the code has multiple entry points to the CALL lea si windowl jmp redraw lea si window2 jmp redraw redraw call si TEXTOUT
257. e got to maintain this old 16 bit Windows code Windows 16 bit architecture DOS Protected mode extensions Global mapping Assembly language PC architecture CPU architecture Mapping Across VMs The question arises when a new VM is created just what is copied and what is mapped back to the original Figure 15 2 clarifies this You will observe some interesting features of this mapping For a start consider the TSR loaded before Windows Because it is a one and only instance any data in it is global across all VMs Think about this it may be good from the point of sharing data but there are no safeguards If one program accesses the TSR and causes its data to be modified perhaps that will clash with another program use of the TSR Commercial TSRs may not be designed with this in mind so it seems wise to minimize TSR requirements prior to loading Windows Notice something else according to my experiments it appears that the entire high memory that is the segment starting at FFFF 010h is mapped back to the original and thus shared across all VMs 344 Windows Assembly Language amp Systems Programming Forced instan tiation Linear address System VM amp physical memory This experimenting was done on a particular system configuration and I cannot guarantee it to be the same on other systems Do not take Figure 12 1 as the gospel truth for all situations but as a starting point for your own
258. e here dumpme PI RK RR IKK KH KH e de Ae e de de RH KR KKK KEE KK IKE KEKE ERK KE KK installhooks jie this ksr already installed i have given it a Signature of CCh push es jjust in case mov ax OCCOOh AL 0 is install test code for 334 Windows Assembly Language amp Systems Programming omy 2A handler int 2Fh multiplex interrupt that we will hook pop es or al al AL non 0 means abort jz abba jmp abort load abba skkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk push cs pop ds mote cs overrides thus not really reqd get a pointer to the name of the load file in the environment seg entered with es psp mov ax es mov Dx es mov WORD PTR cs TSR_info TSR PSP Segment ax sub bx ax e in paras of PSP mov WORD PTR cs PSP Size mov bx 2ch aaa segment mov es es bx xor di di mov cx 1 big number xor al al search for a null cld qq repne scasb get past one null and stop cmp o ptr es di 0 another null jnz no add di 3 skip the word before the name Setting up the Continuing from above look now at setting up the data structure VxD data for the VxD structure prepare part of the instance data list Stuff in pointer to the file name and reference data mov word ptr CS instdata SIS Version 0A03h mov word ptr CS instdata SIS Virt Dev File Ptr mov word ptr CS instdata SIS Virt Dev File peel as es mov word ptr cs instdata SIS Instance Data Ptr 0 mov
259. e listing of VDEMOD ASM follows broken up with comments TITLE VDEMOD example skeleton VxD adapted from a skeleton in Microsoft s DDK It is possible to monitor any I O port and allow or disallow it s use Install_IO_Handler achieves this 386p XLIST l INCLUDE VMM Inc supplied with DDK or VxD Lite Advanced Systems Programming 353 INCLUDE Debug Inc INCLUDE Shell inc LIST ee ee qo s a o eos ogyoo ga ly vyo yna ly Gg GMG ynny M G U GA Da Virtual Device VDEMOD 3 0 VDEMOD Control Undefined_Device ID VMM INIT ORDER Parameters of Device Descriptor Block DOSApp and WinApp access fo the VxD e aes o s ooo vg l G lUe G G M G G Declare_Virtual_Device is a macro that generates a data structure with parameters as listed in the code above The first parameter is the name of the VxD and the macro creates VDEMOD_DDB which marks the beginning of the data structure note that it is exported in the DEF tile The next two parameters are major and minor version numbers VDEMOD_Control is a routine called by Windows to notify the VxD of system events This skeleton only handles initialisation and destruction look below to see how VDEMOD_ Control handles these cases A VxD developer is supposed to obtain a unique ID number from Microsoft I dont know why Microsoft doesnt assign a number with each DDK
260. e old DOS can we still use Then there is the related issue of how DOS itself has been changed to handle the new CPUs and operating conditions What are these 195 196 Windows Assembly Language amp Systems Programming Why use DOS BIOS services DOS in the future changes For example INT 16h the keyboard handler under DOS doesnt work under Windows I have already mentioned the problem of calling the old DOS interrupt services with the CPU running in Protected mode page 33 I introduced some of the first DOS services to utilize Protected mode page 18 Old habits die hard and DOS programmers are going to be loath to give up their familiar DOS and BIOS services in favour of Windows functions especially if some of the old services seem better suited to certain tasks or if the Windows functions dont seem to do anything equivalent or do it poorly In many cases the Windows solutions are painfully slow If you are after performance for certain kinds of applications it may be optimal to use certain DOS services An interesting example comes to mind that of printing Windows printing is designed for dumping a complete page at a time to the printer but if all you want to do is output a line at a time to your faithful old dot matrix perhaps to log some systems events it is darned awkward It is of course a pushover for DOS you can use INT 2 1h to output a single character at a time and when you send a carriage
261. e problem with Windows comes down to lack of speed and unpredictability of response times A hardware interrupt will quite literally propogate through hundreds of instructions before it reaches your application Then there is the general issue of the protected environment you may want to access a particular I O port or memory location but the operating system may prevent access You may want to tweak the system hardware or operating system in some way but not be allowed to The traditional way to obtain unrestricted access to everything is to write a device driver Development of a device driver requires the Device Development Kit DDK and once developed its name must be entered into the SYSTEMINI file in the WINDOWS directory Device drivers are difficult to write and it is a nuisance that the SYSTEM INI tile has to be altered Though with Windows 95 you have the possibility of dynamically loading and unloading device drivers on the fly This chapter however explores an alternative approach It is a technique in which your application can switch up and down between rings 3 and 0 at will without requiring a device driver With this technique you can get nearly all of the benefits of device drivers with fewer hassles 16 and 32 Bit Programming As far as I am aware the first person to publish this technique was Matt Pietrek in an article titled Run Privileged Code from Your Windows based Program Using Call Gates Microsoft
262. e the CPU These are just indexes into the GDT which has the actual addresses You may know that when DOS in Real mode loads a program from disk DOS puts it where there is free memory see page 14 and automatically sets DS ES SS and CS appropriately see Figure 1 8 In Protected mode however the actual addresses of the segments are put in the Descriptor Table while the segment registers only have pointers into the table A small but vital question why Why put the actual addresses out of the CPU in tables The answer is simple segment registers are 16 bits thus limiting the address range to 1M while the segment address in the table is at least 24 bits thus giving at least 16M address range Coding Restraints Yes you can write DOS applications that will run in Protected mode You can see from the above notes that DOS can load code or data above 1M and can also switch into Protected mode and execute the program above 1M The requirement is that the program must not expect actual physical addresses to be in the segment registers Another implication is that the program cannot call the BIOS and DOS I O services normally called by the INT instruction since these are designed to run in Real mode Ditto there is a problem with device drivers and TSRs It is possible to switch back to Real mode just to run an I O service or device driver or Protected mode versions of the BIOS and DOS A Pentium is just a fast 386
263. e to gt intercept an interrupt that being int 0x78 performed by gt a dos application and respond to it from my windows 95 5 application if don t care about interrupt latency time amp amp must write VxD Make Winl6 DLL controlling your interupt vector and processsing interrupts in usual DOS like manner setintvect getintvector if you are happy with Winl app under Windows 95 Make some front end Winl6 app communicating with your Winl6 246 Windows Assembly Language amp Systems Programming DLL else Make Flat Thunk Win32 DLL to communicate with Winl6 DLL Make some front end Win32 app using Flat Thunk Win32 DLL Spend on Win95 MSDN DDK Nu Mega s Soft Ice Write a VxD for Win95 Write your Win32 or Winl6 front end There is a cheap option for developing VxDs known as VxD Lite see Chapter 14 Chapters 12 and 14 explore transitions between DOS 16 bit and 32 bit WinApps and VxDs There are many options for getting at the low level hardware and underlying OS management from 32 bits though it s all awkward Example Now for some example code What I have here is a simple routine program to emit a tone from the loudspeaker Nothing startling but it is loudspeaker significant because it is done by programming the I O circuitry control directly The PC has three hardware timers the first dedicated to producing an interrupt every 55 milliseconds ms t
264. eally be doing it in assembly in line or as separate modules I have included a justification for assembly language at the end of this chapter taken directly from the first edition of this book The main point is that the most productive programming language is not C or C nor is it some augmentation using class libraries and front end code generators Nor is it Pascal Basic Fortran Cobol etc The way to go is visual programming and that does not mean Visual Basic or Visual C These two products are not visual programming languages VPLs as they are still text based languages Borland Delphi and C Builder move slightly further toward true visual programming but it is still mostly the user interface only that is developed visually If you want a definition of VPLs and you have Internet access look at the frequently asked questions FAQ file on COMP LANG VISUAL a newsgroup Much to the dismay of the people who started this newsgroup very few programmers know what a VPL is and COMP LANG VISUAL is bombarded with mail about Visual C and Visual Basic VPLs potentially can increase your programming productivity ten times or more and probably the best of all is LabView developed by National Instruments Corp Pragmatic GOOFEE diagrams Reference sources Advanced Systems Programming 359 I am a realist Obviously writing entire applications or programming substantial portions in assembly language is
265. eap segment is loaded but the original code segment is used This practical functionality is enabled in the DEF file by specifying the data as MULTIPLE see page 177 The same principle can be applied to multiple windows within the one instance Callback One callback Now this is interesting Despite the fact that a program can create but each as many simultaneous windows as it wants there is only one window is a callback function exportwndproc Exportwndproc determines separate which window has sent the message which is easy enough object because its handle hwnd is passed to the callback then it gets the address of the corresponding window object which it loads into SI This is conceptually quite simple Any activity related to the active window on the screen will result in Windows sending a message The callback can use the same code for all windows except for overrides all it needs to know is the address of the object the data and pointers for that window PUBLIC exportwndproc exportwndproc PROC WINDOWS PASCAL FAR hwnd WORD message WORD wparam WORD lparam DWORD LOCAL dummy WORD 5 cmp pwindowflag 0 Make controls this flag jne normalwndproc call DEFWINDOWPROC PASCAL hwnd message wparam lparam 166 Windows Assembly Language amp Systems Programming ret normalwndproc push si callback must preserve si push di and di call GETWINDOWWORD PASCAL hwnd 0 O offs
266. earnt with time as you practise with the machine instructions CPU amp support chips C These registers are 16 bits in Crystal oscillator size so representing the System clock values in hexadecimal g 20 33 notation requires four hex opi 20M digits The address is 20 bits and so requires five hex digits At power on the oe CPU system bus 4 intemal CPU initialises CS and IP as Figure 1 3 shows 8 Math coprocessor ui Power on CS FFFF address IP 0000 BIOS ROM calculation Address produced FFFFO RAM At power on the CPU will put this address onto the other 1 0 chipsCO internal address bus and fetch the first instruction from this address registers Expansion bus interface Includes video adaptor with RAM and BIOS ROM extensio CPU Architecture 11 BIOS ROM Thus the program that takes control when the computer is switched on must start at address FFFFO Furthermore it must be in BIOS ROM so that it is there at power on see Figure 1 3 alongside This program has a special name it is part of the BIOS Basic Input Output System The BIOS routine with the start address of FFFFO takes control of the boot procedure This routine looks for the Boot Record on the system diskette in drive A or C The Boot Record is a small program with certain important system information that is then loaded from disk and executed The Boot Record has already been introduced e
267. eated alias descriptor_selector is ring 0 32 bits but is referencing the same segment The final step is to create the call gate Again an entry is made in the LDT and it is directly written to to make it into a call gate The selector for this call gate is saved as ring0_cs The call gate must contain the offset of the code to be called which in this case is ringOfunc defined as external at the beginning of the code listing You will see that descriptor_selector is also put into the call gate Offset 4 in the call gate which I have marked in the listing with three asterisks is where you can specify how many doublewords you have passed on the stack the CPU will copy these from your ring 3 stack to the ring 0 stack In this case no parameters are copied Now that the stack has been mentioned this is an important issue that must be addressed Windows maintains a separate stack for ring 0 and the call gate will automatically transfer to it The CPU will copy the number of parameters specified from the ring 3 stack and will put the return address on top of the new stack Note that the ring O segment has also been defined in this case as a 32 bit segment which means that the return address is two 32 bit values for selector offset The default ring O stack is very small which is why this program executes CLI clear interrupt before calling the ring O code Have 7go 386P 32 Bit Ring 0 299 a look at the listing an
268. ed addressing mode in that they use certain predefined registers as shown in Figure 2 5 Figure 2 5 is a picture of memory DS SI is where the data is and ES DI is where it s sent MOVSB for example would read a single byte from DS SI copy it to ES DI and automatically increment both SI and DI so that the next time the instruction is executed the next byte will be copied All the string instructions can be postfixed with a B or a W MOVSW would move two bytes of data one word and SI and DI would automatically increment by two 48 Windows Assembly Language amp Systems Programming Figure 2 5 Concept of the string instructions Destination block Auto String operations make use of SI and DI to point to the source and increment destination strings respectively and they are automatically updated each time the string instruction is executed Direction There is a direction flag DF that is cleared by instruction CLD flag DF and set by instruction STD If DF is clear the string instruction will automatically increment SI and or DI to point to the next byte or word and if DF is set they will be decremented It is normal to operate on a string starting from the lowest address in memory so use CLD before a string operation this is the default for the 80x86 family anyway DF is one bit of the FLAGS register shown on page 244 CLD and STD are described in the Appendices REP prefix REP is a prefix placed on
269. edure BP has an offset pointing to a region in the stack segment see page 99 Addresses going down from BP can be reserved by the assembler for local data In the above example if ptr4 was the only local data of DoubleWord size 32 bits or four memory locations then the assembler would equate ptr4 to BP 4 Thus an instruction like lea DI ptr4 would actually assemble with the instruction operation code specially encoded to refer to BP for calculation of the address immediate mode and with the value of 4 as the operand Again I remind you that the MOV instruction with BP relative or index register relative addressing cannot be immediate mode addressing see the golden rule above mov BX Basic Assembly Language 63 Type Override Looking back to that example of a local data label ptr4 see page 61 what if I wanted to see what it contains from within my program wrong mov BX WORD PTR ptr4 mov ES WORD PTR ptr4 2 BYTE WORD DWORD QWORD JWORD SHORT NEAR FAR Type mismatch Size override Accessing 32 bit data in halves The assembler will be rather rude to you if you give it the first instruction The reason is that source and destination operands must always have the same type Type has two aspects to it size and address Size can be of type BYTE 8 bits WORD 16 bits DWORD 32 bits QWORD 64 bits or TWORD 80 bits Address can be SHORT within 128 bytes either way
270. efore I completely forget Should you wish to learn this skeleton and you only have old development tools or you need to modify or maintain legacy code you will find this information useful MASM prior to version 6 00 cant handle the high level language used in subsequent chapters so I recommend upgrading if you dont have it The alternative is the long winded program given in this chapter In fact at the time of writing the latest version is 6 11 and I recommend that you use it in preference to all earlier versions including version 6 10 Microsoft made some important changes in the upgrade from 6 10 to 6 11 Other older assemblers may be able to handle the code in this chapter Borland TASM prior to v2 5 should be ok for this chapter but v2 5 has enhanced features and is the basis along with TASM v3 00 of the program in the next chapter At the time of writing the latest is version 5 0 see Chapter 13 Microsoft Quick assembler should be ok for this chapter I think that Quick assembler version 2 01 can be considered equivalent to MASM version 5 2 All of this upgrading is difficult to keep up with but the above notes should prove helpful Of course as mentioned above with some language products such as those from Borland you dont need to have the SDK installed though I certainly recommend the SDK documentation Note that even if you are only interested in writing in line assembly within your high level code cons
271. el language Thats saying something What follows is a breakdown of each section of the previous program showing how it can be improved Include Files Refer back to page 94 You will see a whole pile of equates for example WM PAINT EQU 15 WM_PAINT is simply a meaningful label a constant that equates to value 15 This means that wherever the assembler finds the label WM_PAINT it will be replaced by the value 15 109 110 Windows Assembly Language amp Systems Programming INC files Structures defined in INC file Assembler version notes These semi English labels are more meaningful to us and therefore make programming easier Windows has hundreds of these predefined equates though the example program only uses some of them Those people familiar with writing Windows programs in C will recognize this INCLUDE lt WINDOWS H gt It is a statement placed right near the beginning of the program and has the effect of inserting the file named between the lt gt into the program at that point WINDOWS H contains all of the equates plus other definitions such as structure definitions Windows programming also makes extensive use of structures look back to page 65 for an introduction to structures Microsoft versus Borland Instead of explicitly naming all the equates and structures in my program as I did for the first example program an assembly language program can also include WINDOWS H Or rather
272. embly Language amp Systems Programming Note also a particular problem due to the temporary nature of local data with regard to getting its address within the program see page 60 This local data can be referred to by name and the assembler will do the job of equating the labels to bp value A most useful side effect of local labels is that the names are only recognized within the current procedure not even inside nested procedures This means that you can use labels elsewhere with the same names this is a highly qualified statement refer to page 120 The syntax is not part of program listing LOCAL label type label type ll STRUC directive Notice the data types WNDCLASS and MSGSTRUCT above Structures are introduced back on page 65 Structures used by Windows are defined in WINDOWS INGC the Include file WNDCLASS and MSGSTRUCT are the names of structures and they can also be used in data declarations as the data type as has been done with our LOCAL declarations sl and s2 sl is merely an instance of structure WNDCLASS while s2 is an instance of MSGSTRUCT For your reference extracting the definition of WNDCLASS from Borlands WINDOWS INC not part of program listing MSGSTRUCT STRUC NOTE DW 2 BETA DW For 32 bit programming all of msWPARAM DW these fields become 32 bits Let Sale a The Companion Disk has msPT DD 2 different Include files For 16 bit MSGSTRUCT ENDS Windows a
273. embly error with ML due to a clash with the PROTO declaration The idea behind this is the extra safety checking that high level programmers are accustomed to ML has two very convenient mechanisms for defining a 32 bit parameter ADDR is a directive that will pass the NEAR or FAR address as appropriate The other mechanism is where we pass a FAR address in two registers In the skeleton program you see this done often in ML we combine them with double colons for example ss bx You can see this in action on the Companion Disk and the listing at end of this chapter Microsoft has put a lot of thought into making MASM6 behave like C despite a very different syntax There is a utility called H2INC EXE that will convert a C Include file H into an assembler Include file INC Most importantly if used on WINDOWS H it will produce the prototypes for the Windows functions so we dont have to type them in This WINDOWS INC is peculiar to MASM6 and dont expect it to be usable by TASM The reverse is ok however MASM6 happily reads the High Level Assembly 129 WINDOW INC that Borland supplies with TASM and licenced from Microsoft actually I used H2INC to generate a WINDOWS INC for the example program though note that I had to edit it somewhat the NC file to get it to work with my assembly program Callback Design So you can very happily go through the earlier TASM program of this chapter replacing CALLs with INVOKEs a
274. en more than that allowing us to program at a more abstract level Instead of being concerned about the precise hardware details of the I O device that our program is dealing with we can use the Device Independent Graphics graphics device interface GDI tools Translation from our program to the particular device is taken care of by device drivers and our program can have code that will work on a wide range of different devices such as various video standards for example Hercules CGA EGA and VGA Internal Differences Of course the results appear on the screen but the fundamental structure of our Windows program is different from a DOS application The rest of the chapter is devoted to exploring those differences and the design methodology required to implement them such as handles and messages A Windows program is what we call event driven The entire structure revolves around this concept Those of you who have done any programming at all under DOS will know how to read a character from the keyboard In assembly language you could use INT 16h AH 0 However with Windows we don t do that In fact INT 16h won t even work Windows will hang The essence of being event driven is that for mouse keyboard and much other input we don t write code to explicitly ask for input Instead we perform a call to Windows requesting a message and Windows will send any message that it thinks is relevant to our program Thus
275. engineers realized this to be a problem and solved it by introducing three more segment registers DS Data Segment SS Stack Segment and ES Extra Segment To support these registers the designers introduced the EXE executable file structure that allows code to be stored in the segment pointed to by CS data to be in another segment pointed to by DS the stack to be in yet another segment pointed to by SS and ES to be a segment that can be used by the application programmer Figure 1 8 shows a pictorial representation of how these registers might be laid out in memory EXE Although segments are still only 64K maximum it is possible to executable have multiple segments of code and data for large programs file format One aspect of the headache associated with segments is this 64K limit Obviously large code or data could exceed this and problems arise Another aspect is that this segmentation scheme of addressing has carried over to the 286 386 etc again for compatibility reasons CPU Architecture 17 Figure 1 8 EXE program segments Resident part of DOS 20 bit starting address of the code segment is i e 4 binary 0 s stuck onto the right side or one hex 0 digit Instruction y 20 bit address The 20 bit address The next instruction to be is applied to the executed is pointed to by extemal address IP 16 bit which is an bus to fetch an offset from the start of instruction the segment l Increasing
276. ent the operand of the instruction will have to contain the destination CS IP which is two 16 bit values Hence it would be 32 bits The FAR jump would assemble as the one byte or two op code followed by a one word IP then one word CS value Note that the FAR jump can also jump within the current code segment but is slightly inefficient because it is a longer instruction taking a little longer to execute and using more memory The IMP instruction has one interesting difference from the CALL it is able to perform a SHORT jump This is shown in Figure 2 4 Figure 2 4 SHORT jump machine code Increasing Operation code_ addresses downward V This reduces the instruction down to the one byte 8 bit op code followed by a one byte 2 s complement displacement This displacement allows jumps to be only 127 to 128 about the current IP position In some circumstances the assembler will automatically make the jump SHORT but it can also be forced to by means of the SHORT directive Conditional Jump The conditional jump instructions test various flags before deciding whether to jump or not These instructions are always of the SHORT type This is very important they can only jump 128 locations away from the current code location The conditional jump instructions are sometimes confusing for the student however the concept becomes quite clear with a little practise Most CPU instructions affect the flags after they
277. equates could have been in an include ile define IDM QUIT 200 define IDM_ABOUT 201 winasmoo MENU BEGIN POPUP File BEGIN MENUITEM Quit IDM_QUIT MENUITEM About IDM ABOUT END END Program Design 77 ICON_1 ICON winasmoo ico Definition file The icon resource is arbitrarily named icon 1 so when I created window1 in my program I put in the override sziconname icon There is a useful note that I can make about the DEF tile so here it is WINASMOO NAME DESCRIPTION EXETYPE STUB CODE DATA HEAPSIZE STACKSIZE EXPORTS Multiple instances SMALL model Virtual Method Table Demo 00 asm program WINDOWS WINSTUB EXE PRELOAD MOVEABLE PRELOAD MOVEABLE MULTIPLE 1024 8192 exportwndproc What I would like to point out in particular here are the specifications for the data segment PRELOAD means that it loads when the program is first loaded MOVEABLE means that it can be moved by WINDOWS MULTIPLE means that every instance will have its own copy of the data segment The latter point is important if you want the program to support multiple instances I have designed the code to support multiple instances with the same ease that it supports multiple windows within the same instance but this only works if each instance has its own complete copy of the data stack heap Note that all instances will use the same code segment which is no problem at all This works because c
278. er 121 1 concatenation 128 Operator 143 gt object pointer 144 ASM source program 73 ASM stub 148 150 COM format 16 47 DEF tile 73 89 DLL and DRV tiles 72 EXE format 16 H to INC translator 128 ICO file 73 176 INC file 73 110 MAK file 73 MODEL directive 111 119 RC resource file 73 89 RES tile 74 2 286 internal architecture 21 2 s complement 7 51 3 32 and 16 bit segments combining 298 32 bit data accessing in halves 32 bit instruction pointer EIP 4 32 bit Real mode 291 32 bit registers 11 20 32 bit versus 16 bit programming 288 386 coding specifically for 23 386 internal architecture 21 8 d bit CPU 12 80286 386 CPU 9 16 18 21 803 1 186 8042 186 8086 88 CPU 9 12 13 15 A Access field 28 253 289 Accessing 32 bit data in halves 23 130 Accessing data 58 Accessing physical memory in a VM 344 ADC instruction 53 ADD instruction 52 ADDR 128 Address bus 9 Address decoder 182 Addressing below M from prot mode 228 Addressing modes ALE signal ALLOCCSTODSALIAS ALLOCDSTOCSALIAS ALLOCSELECTOR ALLOCSELECTORARRAY AND instructions Application program skeleton Application queue Application structure Arithmetic instructions ASCII ASM OVP compiling from C ASM stub from C Assembling amp linking Assembly faster smaller etc Assembly in line Assembly language binding Assembly versus high level AUTOEXEC BAT Automatic data Automatic loading of WinApp VxD B
279. ere is virtually no further clarification about what you can and cannot use and under what conditions and circumstances Furthermore the SDK 3 1 documentation does not have this warning The Windows 95 SDK just about ignores BIOS and DOS interrupts entirely I have already mentioned that INT 16h the keyboard handler works tine except that you need to be aware that Windows hooks the INT 9 hardware vector that puts characters from the keyboard into the keyboard buffer Windows has its own 128 character buffer and its own keyboard handler Leaving the standard BIOS and DOS services for now I will focus on DPMI DOS Protected Mode Interface DPMD Reference The main sources of information for DPMI are the specification sources itself DPMI Specification version 1 O DPMI Committee 1991 This committee is hosted by Intel Corporation and members include Microsoft IBM and Borland Further information is in Microsofts DDK and in Writing Windows Device Drivers by D A Norton Addison Wesley USA 199 1 and on line at http www delorie com djgpp doc I have summarized the major DPMI services in Appendix C and you will find practical code with further explanation in subsequent chapters DPMI What follows are some of the underlying principles of DPMI If elsewhere in any of it doesnt make sense dont worry as it should be much this book clearer when actual code is shown in the next chapter I have also provided more underly
280. erences to FAR pointers over the next four pages Always keep in the back of your mind that for the 386 the distinction between NEAR and FAR becomes blurred you will see why LES LDS and LEA Instructions As my example code further on in the book makes use of these instructions some clarification is in order here CODE mov DI OFFSET place2 mov ES SEG _ place2 les DI place2 s 1 Example of what NOT to do place2 Although I have implied that place2 is a code label in the current code segment let s assume that it is in some other code segment maybe in a large EXE program with multiple code and or data segments The first two MOV instructions will load the FAR address of place2 into the two registers ES DI LES with However the LES instruction will not work I have put it here to code labe emphasize this point LES and LDS also LGS and LFS are operand constrained to non immediate addressing mode only they are designed to load pointers What will happen here is a type MOV addressing mode limitation Restriction of OFFSET directive routine2 LOCAL Basic Assembly Language 61 mismatch error because place2 is a code label The operand of these instructions must be a data label as it is the content of the label that is loaded Read ahead to see code in which it does work Whenever you want to load a segment and or offset use the MOV instruction as shown above or LEA However in some
281. erface with the hardware of the computer such as the keyboard screen printer disk drives and serial port These service routines existed before Windows was conceived of so are primarily designed for use with DOS They still work under Windows but there are many ifs and buts here Complete books have been written around this issue DOS itself is really the COMMAND COM program In the case of Windows 3 x DOS is started first i e COMMAND COM then WIN COM are executed COMMAND COM is the keyboard interpreter It reads what you type at the keyboard and obeys your command If you tell it to load another program such as WIN COM it will do even though it means starting another operating system Windows on top of DOS Windows 95 simply eliminates the COMMAND COM step but COMMAND COM is loaded if you start a DOS box inside Windows or choose to exit to DOS from Windows COMMAND COM contains the routines that interpret the commands from the keyboard when we are in the DOS command mode Note that there are two classes of commands internal and external The internal commands are contained within COMMAND COM while the external commands are kept on disk FORMAT COM for example is the program for the FORMAT command and is external DIR is internal The reason that some of DOS s commands are kept as separate programs on disk is due to space constraints in RAM Obviously there is limited RAM so it makes sense to keep the less u
282. errupt goes into the IRQ1 input of the Interrupt Controller chip hence to the CPUs interrupt input IRQ Question how does the CPU know that a keyboard interrupt is INT 9 e to look at the ninth entry of the interrupt table for the address of the keyboard handler routine Answer The CPU and the Interrupt Controller communicate automatically over the data bus and take care of this detail INT 8 to INT F correspond to IRQO to IRQ7 With the AT class PC though a view under the hood shows that the 803 1 sends a Kscan byte for each key press release which the 8042 converts to the normal scancode Thus it may be that we never have to encounter Kscan codes unless our work involves directly programming the 803 1 186 Windows Assembly Language amp Systems Programming Keyboard This is the basic structure of INT 9 in the BIOS as pointed to by housekeeping entry 9 in the IVT disable keyboard AT in al 60h read scancode from PA push ax save it in al 6ih read PB or al 80h set PB7 1 out 61h al and al 7Fh clear ai out 61h al POP ax INT 15h AT only Check for keyboard commands Resend Ack Overrun AT only _ Update LEDs AT only process key issue End Of Interrupt EOI AT Class Keyboard Port Enhancements Port 60h has been expanded beyond that of merely reading the scancode from the keyboard as was its sole role in the earlier XT model PC Now there are two g
283. errupt occurring It pushes CS IP and flags on to the stack and gets the new CS IP from the IDT The other registers are as they were before the interrupt Thus upon entry to the service routine only CS is set to the code segment of the service routine How do you access data in the service routine One solution is to put data into the code segment Normally this is not allowed or rather it is but you can t write to it because code descriptors have their access field set to read only however DPMI has a service that gets around this very nicely What you can do is obtain an alias that is a data selector that Implementation as a DLL does have some advantages however If a DLL segment is declared FIXED in the DEF tile it loads below 1 M and is also guaranteed to be in contiguous memory These features allow the DLL to have Real mode code as well as Protected mode code The DLL runs at privilege level 3 level 1 in Windows 3 0 so I O still causes an exception 2 MAKEPROCINSTANCE can be used to attach prolog code that binds data to code though I have not used it here for certain reasons See further notes in the Companion Disk 254 Windows Assembly Language amp Systems Programming points to the same code segment This will allow you to write to the code segment Windows has various functions for segment manipulation though many of them were unofficial until 3 1 was released Of most interest is CHANGESELECTORQ
284. ers from previous destroyed virtual machines programs should monitor changes to virtual machines to ensure no mismatches interrupt 2Fh Function 1684h Get Device Entrv Point Address Retrieves the entry point address for a virtual device s service functions MS DOS device drivers or TSRs typically use this function to communicate with virtual devices they have explicitly loaded Call with AX 1684h IBX device identifier ID Return value The return value is the entry point address contained in the ES DI register pair if the Function is supported Otherwise ES DI contain zero Comments Any virtual device can provide service functions to be used by MS DOS programs For example the virtual display device provides services that the Windows old application program uses to display MS DOS programs in a window It is the responsibility of the MS DOS program to provide the appropriate virtual device dentifier The function returns a valid address if he virtual device supports the entry point MS DOS programs call the entry point using a ar call instruction The services provided by the virtual device depend on the device It is the esponsibility of the MS DOS program to set gisters to values that are appropriate to the specific virtual device tor versions of Windows prior to version 3 0 he program must set the ES DI register pair to rero before calling this function 408 Windows Assembly Language amp Systems Progr
285. ers from selector to segment value Then the handler will have to look in the IVT to get the address of the Real mode service Thus even the services in the BIOS ROM will work At least they will return without crashing the system in most cases though whether they do what you want is another matter Note however that there is a difference in accessing interrupts from a 32 bit compared with a 16 bit Windows application This is a complicated issue and is developed in Chapter 16 Another fascinating thought occurs about virtual 86 mode which uses the IVT but in plural Although there is an IVT at actual physical address O0OO0 0000 each virtual 86 task will have its own copy of the IVT which appears to be at 0OOOO O000 but is paged anywhere You need to be aware of this proliferation of IVTs if you want to hook a vector Refer to Chapters 10 11 and 12 for more information particularly page 282 and thereabout 36 Windows Assembly Language amp Systems Programming Postamble This chapter mapped out the overall architecture of the x86 processor and you may have found some of it heavy going Subsequent chapters are a step back and topics are revisited in depth Chapter 2 is an in depth treatment of the basics of assembly language Content of this chapter Basic Assembly Language Preamble This chapter contains an introduction to assembly language for the x86 family of processors The focus is on 16 bit programming
286. es For example the DOS VMs are located at linear address range 8100 0000 to FFFF FFFF If youve been following this with an attentive mind you may see a problem here wont each DOS VM be in its own completely isolated virtual address space Yes but this is an example of where Windows maps different virtual addresses to the same physical place Thus from the system VM you can use the above address range to access the DOS VMs just as though they exist within the system VM Another reserved area in the VM is the range 8000 0000 to 803F FFFF where the virtual device drivers are kept We lump a DOS V86 VM and its Protected mode together as one VM so each VM has its own attached Protected mode and hence Intels DPMI specification has various warnings about function 0800h This function should only be used by clients that absolutely require direct access to a memory mapped device at physical addresses above 1 M Clients should not use this function to access memory below the 1 M boundary Programs and device drivers that need to perform DMA I O to physical addresses in a virtualised hardware environment should use the Virtual DMA Services 348 Windows Assembly Language amp Systems Programming its own 4 3G space However there needs to be a further clarification what about overlapping of the addressing while in Protected mode or in V86 mode Yes the two do overlap V86 addresses linear address range 0000 0000 to OOOF
287. es as shown in the second half of this chapter The polymorphic principle Object pointer passed on the stack Program Design 141 TEXTOUT could be a routine that sends text to a window but there could be many such routines designed for different output mediums In this case I have arbitrarily created a class WINCLASSB that overrides the pointer with textoutdlg while WINCLASSA does not The key point here is that I can call TEXTOUT but because it is a pointer the actual routine that gets called depends upon what is stored in that field In the case of instance windowl it is textoutmain and in the case of window it is textoutdlg You could imagine two windows of different types on the screen requiring different textout routines C uses THIS to specify which instance object is currently being referenced Each sub class and indeed each instance of a class can have its own TEXTOUT function so our code must be able to distinguish Look again at the above listing to see how I have done it I have disassembled a lot of C code to find out what makes it tick Borland usually put the value of THIS into SI which may be worth noting if you have to interface with C code When coding at the assembly level we need to think carefully where we want to store THIS if anywhere at all Notice that I also used SP to hold THIS see the code examples in previous listing Whenever Borland C calls a function member it a
288. es useful if you need to build a 32 bit structure that contains pointers and pass a pointer to it and free the Win32 DLL I hope you can read C code I have taken these examples straight from the SDK documentation 220 Windows Assembly Language amp Systems Programming The following prototypes should be used DWORD FAR PASCAL LoadLibraryEx32W LPCSTR DWORD DWORD DWORD FAR PASCAL Get ProcAddress32W DWORD LPCSTR DWORD FAR PASCAL Call1Proc32W DWORD LPVOID DWORD DWORD DWORD FAR PASCAL Get VDMPointer32wW LPVOID UINT BOOL FAR PASCAL FreeLibrary32W DWORD Note that although these functions are called in 16 bit code they need to be provided with 32 bit handles and they return 32 bit handles Do not forget that the 32 bit functions must be called with the STDCALL convention CallProc32W CallProc32W follows the PASCAL calling convention It is designed to take a variable number of arguments a Proc address a mask and the number of parameters The mask is used to specific which arguments should be treated as being passed by value and which parameters should be translated from 16 16 pointers to Flat pointers Note that the low order bit of the mask represents the last parameter the next lowest bit represents the next to the last parameter and so forth Code I didnt really want to put actual code into this chapter but a little examples sample of Generic thunking is useful while Im on the topic Assume
289. essages at once Hardly useful if you want your application to be triggered at precise intervals As a final thought Windows has an undocumented function CREATESYSTEMTIMERO that is documented in the DDK Daniel Norton s book see page 203 and in Undocumented Windows see page 218 It bypasses the message queue and calls the callback directly Thus it is possible to make code execute at precise intervals though the callback has the major restriction that it can only call certain Windows functions just like an ISR Threads Windows 95 has made timers less important with the introduction of threads These introduce an execution overhead though Threads are only supported in 32 bit applications with the Win32 API Even though a 16 bit application can call 32 bit API functions see thunking section in Chapter 8 it cant use the 248 Windows Assembly Language amp Systems Programming thread functions Threads can synchronise their execution also see Chapter 8 page 223 10 Real Time Events Windows preemptive aspects Application preemption Preamble So you think 16 bit Windows applications are non preemptive Think again Just about everything you read will tell you that a disadvantage of Windows 3 x is non preemption That is once control is passed to an application Windows cannot regain control until the application has passed control back by a RET One of the touted advantages of 32 bit applications under
290. et in Windows internal data mov pwindow ax get addr of current window object mov si ax don t use LEA Saving amp Dont worr about pwindowflag for restoring a GETWINDOWWORD is a Windows function that returns pointer to a information about the window that Windows has stored internally window The intention here is that I have the handle to the window hwnd object and I want to know the address of the object for that window In the case of my simple skeleton program there was only one window anyway and I created the window1 object for it refer to page 153 There is a bit of a trick here because when I used make to create the window I also gave the address of the object to Windows for Windows to store as part of its own record about that window GETWINDOWWORD enables me to retrieve any information that Windows has about that window plus the extra information I gave it This is a mechanism for associating a particular set of data in this case object windowl with a particular window I stored my special data at an offset of O in Windows internal data structure so here I get it back returned in AX I then put the address into the global pointer pwindow and into SI mov ax message save params in window object mov si wmessage ax mov ax wparam mov si wparam ax mov ax WORD PTR lparam mov WORD PTR si lparam ax mov ax WORD PTR lparam 2 mov WORD PTR si lparam 2 ax call si
291. eturn value This function has no return value Comments The VDD calls this function only if the VM application has called Enable VM Assisted save Restore Interrupt 2Fh Function 4000h E3efore calling this function the VDD restores my registers it modified to the values they had vvhen the VM aoolication originally called Enable VM Assisted Save Restore In other words every register is guaranteed to be either unchanged or reset to a previous state precisely which registers may be reset is undefined but the set is restricted to those Sequencer and Graphics Controller registers that do not affect the display Interrupt 2Fh Function 4007h Disable VM Assisted Save Restore Directs the virtual display device VDD to discontinue notifying the VM application when it needs access to video registers VM applications call this function when they terminate Call with Ax 4007h Return value This function has no return value Comments This function directs the VDD to restore I O trapping of unreadable registers and to discontinue calling Save Video Register State and Restore Video Register State Interrupt 2Fh Functions 4005h and 4006h when it needs access to the registers Furthermore the VDD ignores any subsequent calls to Enter Critical Section and Exit Critical Section Interrupt 2Fh Functions 4003h and 4004h This function does not disable Notify Background Switch and Notify Foreground Switch Interrup
292. ew we wwe ee sub ax ax returns 0 in DX AX callback functions cwd return a 32 bit long value xreturn ret ASMDEMOPROC ENDP ee a END astart xname of startup code Run time Here is an exercise Locate the above program in ASMDEMO2 IFI on the Companion Disk and assemble and link it When you have ELSEIF succeeded have a go at modifying the code with something ELSE wonderful available in MASM6 Borland did not catch up with this capability until TASMS Pomc ax WM_CREATE gt Runtime IF ELSEIF ELSE ex note that nesting is allowed ELSEIF ax WM_PAINT ELSEIF ax WM DESTROY ELSE _ENDIF If you cant quite see how to use this look at the skeleton in Chapter 13 Run time high level IF ELSEIF ELSE constructs tidy up your assembly code enormously and Im hooked on it Note that it assumes nothing and does not change any register values This 136 Windows Assembly Language amp Systems Programming means that you can jump out from anywhere and jump around inside like this IF ax 0 jmp placel goto anywhere quite legal ELSEIF ax placel ELSEIF ax jmp place2 ENDIF place2 Your mission should you decide to accept it is to introduce the high level decision constructs to the above example program You will also find other high level constructs in the MASM6 and TASMS manuals such as DO WHILE History of OOP and assembly A rationale for OOP Program Design
293. fixes Types of handle The asterisk means that these sizes only apply to 16 bit applications For 32 bit applications they are all 32 bits We should make use of this notation wherever possible while writing programs as it improves readability The source of Table 3 1 is Thorn Hogan s superb book The Programmer s PC Sourcebook by Microsoft Press second edition 1991 Of course BYTE is 8 bits WORD is 16 bits and DWORD is 32 bits Unfortunately Thorn s book is out of print It is common practise also to use s for string and sz for zero terminated string Combinations are allowed for example Ipsz means long pointer to zero terminated string For 32 bit applications the distinction between a long pointer and a pointer is blurred so the prefixes p and lp can mean the same However it is a case of do as I say not as I do For old habits die hard I do tend to lapse back into non Hungarian naming of data labels and where you encounter such lapses forgive me Mostly I have not followed the Hungarian notation when writing Windows aware DOS code examples of which you ll see in Chapters 10 11 12 and 14 I have described the handle as being used to access almost all resources However it is useful to formalize this Again the original source of this tabular information is Thorn Hogan s book Refer to Table 3 2 below Table 3 2 Types of handle NAME UNCTION
294. flag hook IVT vectors 28h and maybe 1Ch shook int 2Fh vector in ivt Windows calls this with AX 1605h when it loads with regs telling useful info such as if loading in Standard or Enhanced mode mov ax 352Fh get int 2F vector in ivt int 21h 7 mov oldoffivt2F bx save it mov oldsegivt2F es mov ax 252Fh hook int 2F lea dx runtime2F set ivt vector int 21h doit mov ax 2561h hook INT 61h so signaller can find lea dx callback forwarder in system VM from int 21h another WVM hook keypresses releases mov ax 3509h get int 9 vector in ivt int 21h 326 Windows Assembly Language amp Systems Programming mov oldoffivt9 bx save it mov oldsegivt9 es i rd mov ax 2509h shook int 9 lea dx runtime9 set ivt vector int 21h initialise int 60h in ivt as used to test if WinApp has hooked it push ds actually this will be 0 0 anyway but make sure tough luck if some mov ax 0 other App has hooked it mov ds ax mov dx O mov ax 2560h put 0 into int 60 int 21h this hook will be in all Vm s pop ds lea dx endprog 17 point past all code in this module Note that an optimum program would relocate the install portion of code at the end so it can be discarded shr dx 4 compute paragraphs to keep mov ax 3100h terminate and stay resident int 21h runtime 9 jthis is now the signaller it is entered at every key press release but only when in Real mode
295. free to jump over any parts that you are already familiar with I recommend going through it with the objective of picking up the overall ideas not worrying too much about nitty gritty details A practical plan of action is to surge forward until you get to the chapters with some hands on examples then when you need to know some of the fine details refer back as needed You ll find the index to be comprehensive with this in mind In keeping with the ladder concept I have covered the entire x86 family of processors from the humble 8088 to the Pentium It is very important to note that these later CPUs are downward compatible meaning they will run software from an earlier CPU though the reverse is not necessarily true In this chapter I point out some of the major differences between the CPUs of the Intel family I 2 Windows Assembly Language amp Systems Programming A grassroots approach As the book develops we get into areas of programming that will require you to have a knowledge of the architectural concepts presented in this chapter This book is about Windows programming and can even be used as an introductory text for Windows but the emphasis is at a more fundamental level than found in other Windows programming books Having such a fundamental knowledge will make it easier for you to do all kinds of tricks with Windows such as direct keyboard input direct video output and signalling via interrupts Po
296. g OFFSET label if label is defined in the data or code segment For temporary data always use LEA reg label 62 Windows Assembly Language amp Systems Programming LES with data label operand How the assembler equates automatic data abels Some further clarification the local data label ptr4 only exists within routine2 LEA will load the offset ptr4 into DI LES DI ptr4 will load the content of ptr4 into ES DI non immediate mode since ptr4 is a data label which is the only mode LES can handle Note that LDS works like LES but loads DS instead of ES The LEA instruction differs from the other two in that it loads the offset of the label regardless of whether it is a data or code label LEA DI placei for example would just load the offset NEAR address of placel into DI not the segment value Local Data An example is given above and there is more explanation in Chapter 5 So far I have been treating labels code and data as being equated by the assembler to their addresses But what of the case of local or automatic data labels that only come into existence when execution enters the procedure in which they are defined The assembler equates local labels to BP value where value is known at assembly time but the BP register will have a certain value at execution time If you want to know more about the special role of the BP register study Chapter 4 Basically when execution enters a proc
297. g musicflag DB 0 turn music on off runtime pusha save all regs push ds push es mov es cs dsselector get alias push es scan also set ds to alias pop ds so seg override isn t needed to access data Real Time Events 255 sti enable interrupts STI and reentrancy issues discussed on page 323 cmp musicflag 20 musicflag is used as a counter for jb jumpout3 turning the tone on or off on each fF mov musicflag 0 710th entry to the routine fF jmp turnoff F jumpout3 inc musicflag cmp musicflag 10 jne jumpout2 timeron mov al Ob6h sturn on the hardware timer out 43h al mov bx 07cSh frequency 600Hz mov al bl out 42h al mov al bh out 42h al in al 6l1h or al 03 out 61h al im SHORT jumpout2 in al 6ih turn off the hardware timer out 61h al jumpout2 POP es Pop ds prestore all regs popa iret Testing Stick this service routine somewhere in your program then assemble and link as per normal To test it you will have to modify some other program by inserting an INT 16h instruction into it Perhaps you could put this instruction into the other program s WM_CHAR case so whenever you press a key and the other program s window is active the program will execute INT 16h which will call the service routine Don t be confused here A key press has nothing to do with INT 16h under Windows at least as far as normal code is concerned I have just arbitrarily suggested tha
298. g MS DOS device drivers and TSRs that monitor Interrupt 2Fh the opportunity to prepare for running in the Windows environment Call with AX ES BX DS SI cx DX 605h 0 0 O om 0 normally Specifies whether standard or 386 Enhanced mode Windows is initializing 386 Enhanced mode Windows sets bit 0 to 0 standard mode Windows sets bit 0 to 1 Only bit O is used all other bits reserved and undefined Specifies the version number of Windows The major version number is in the high order byte the minor version number in low order byte Return value The return value is O in the CX register if all MS DOS device drivers and TSRs monitoring Interrupt 2Fh can run in the Windows environment and Windows can proceed with initialization Otherwise the CX register is nonzero and Windows must terminate Comments Anv MS DOS device driver or TSR that either cannot run in the Windows environment or must adapt its operation when in the Windows environment should add itself to the Interrupt 2Fh chain and watch for this function If the device driver or TSR cannot run in the Windows environment it should set the CX register to a nonzero value display a message informing the user of its incompatibility with Windows and return Windows does not print a message of its own Instead it calls Windows 404 Windows Assembly Language amp Systems Programming Heading Description Call with Returns Termination
299. g The instance declaration of a conventional structure would require the message a very rigid syntax of comma delimiters Here all you have to do handlers is override only those fields you want and you can put them in between the in any order No commas are required for unchanged fields You need to have an understanding of each field of the WINDOW structure to make use of them in the program Create paint timer etc down to destroy are the main WM_ messages that Windows sends to the callback function I have only implemented the WINDOW sstructure with these although there are many more The others all go directly to Windows default handling You are quite welcome to expand the structure with more messages Overriding Definewndclass defaultproc destroy make and wndproc the major are major routines within WINASMOO INC By putting them in hidden the structure you can override them for any sub class or instance functions of For example wndproc is a pointer to the callback function for the Include that window it basically performs a case switch calling the file appropriate message handler create paint timer etc But there is nothing to stop you from overriding it and defining your own special calllback say for example to handle a dialog box These pointers are probably ones that it would be wise to leave alone until youve become familiar with this software Data members of The rest
300. g Windows Initialization Notification Interrupt 2Fh Function 1605h In particular virtual devices may call Device Call Out Interrupt 2Fh Function 1607h or other functions prior to Windows calling this function In such cases any MS DOS device driver or TSR responding to these calls is responsible for detecting and properly handling these calls Interrupt 2Fh Function 1609h Windows Begin Exit Notifies MS DOS device drivers and TSRs that Windows is about to terminate Windows calls this function when it first begins termination to allow a device driver or TSR to prepare for a return to a non Windows environment Call with AX 1609h Return value This function has no return value Comments Windows calls this function at the start of the Sys VM Terminate device control call All virtual devices still exist so a device driver or TSR can call a virtual device s entry point if necessary Windows does not call this function in the event of a fatal system crash Windows may execute Real mode code after this function has been called and before 386 Enhanced mode Windows returns to Real mode It is the responsibility of the device driver or TSR to detect and properly handle these situations Interrupt 2Fh Function 160Bh Windows TSR Identify This information is missing from the DDK When Windows and Windows Setup start they broadcast Interrupt 2Fh Function 160Bh to notify TSRs and MS DOS device drivers A Windows aware
301. g the Window s screen INT 2Fh AX 4001 2h Direct Hardware Access 229 what the 386 actually puts out In the case of the 286 it will only be 24 bits Look carefully at that above code fragment See that I treated the selector as the exact equivalent of the segment paragraph address it represents Behind the scenes the CPU will use the selector value in ES to lookup the LDT and get the physical address This service is wonderful because it gives you direct access to all memory below 1M It also gives you enormous potential to stuff up the system Pardon the crudeness but theres more than one way to skin a cat Ditto with DPMI services and low level Windows functions If the two overlap which ones do you use Interestingly some of the Windows functions internally call the DPMI services In the above case the Windows function equivalent is well there are choices here just as there are some different avenues with DPMI SETSELECTORBASE is appropriate it creates a new entry in the LDT and will set the base address linear address field in the descriptor You provide a selector value as a parameter to this function the descriptor of which is used as the model for the new descriptor So if you want to treat the new memory block as data use DS as the model The SDK 3 1 documentation does not explain any of these vital details Note that SETSELECTORBASE is available in Windows 3 0 but was undocumen
302. gment This enables me to write to the code segment Into the code segment I saved the handle hwnd of the application s window The reason for this is that within the ISR I called POSTMESSAGE which needs the handle as a parameter Calling the You can see that I hooked the vector and saved the old vector but old handler I also put the old vector into INT 60h That is I hooked INT 60h so that it now points to the Windows keyboard handler This is convenient because from within the ISR I wanted to be able to call the old ISR for proper handling of the keyboard input Note that there are other ways of doing this such as by use of a CALL instruction Now for the ISR runtime int 60h call the old INT 5ih pusha save all registers push ds push es push ss mov ax cs hwndcs get window handle t call POSTMESSAGE PASCAL ax WM_USER O 0 0 no will do it this way as PASCAL qualifier very inefficient push push push push push call POP ss POP es pop ds popa iret ax WM_USER 0 0 0 POSTMESSAGE put message on queue snow restore and get out Real Time Events 263 installint ENDP END INT 9 keyboard handler Real mode keyboard handler See how simple the ISR is I was able to call the original keyboard handler for proper handling of the key press release though note that I could have put the INT 60h at the end of the ISR if required I accessed hwndcs the handle of the window passed a
303. gram is supposed to know but an undocumented feature of INT 2Fh function 168Ah with address of string MS DOS in the SI register returns a selector to the start of the LDT 298 Windows Assembly Language amp Systems Programming Creation of a ring 0 code descriptor 16 32 bit code in same segment Call gate fields Ring 0 stack The next job is to create a descriptor for the ring O code This is a SMALL model program which means that all code is in the same segment ALLOCSELECTOR creates a new descriptor in the LDT that is an alias to in this case CS The code immediately after uses the selector to the LDT to directly access the LDT and modify the privilege level of the segment Also since the newly created descriptor is an alias to CS it is a 16 bit segment this example code requires the ring 0 code to be 32 bits by default Therefore the seg_16 32 bit is altered also Normally an application cannot directly modify an entry in the LDT for the simple reason that you don t know where it is Now having modifed it you can t call it because it is a ring O descriptor whereas your code is running at ring 3 Note that there is a trick being performed here as there is only the one segment I defined ASMRINGO as SMALL and when the ring O file HEAVEN is linked there will only be one code segment CS is a ring 3 16 bit descriptor so that is how the code is treated when executed using CS However the newly cr
304. gramming Thie geannam makes use of BIOS DOS amp low level Windows functions remember that Windows funcs only preserve SI DI BP amp DS INCLUDE WINDOWS INC INCLUDE WINASMOO INC IDM QUIT EQU 100 IDM ABOUT EQU 101 DATA windowl WINDOW szclassname DPMI sztitlename DPMI DEMO paint wlpaint create wlcreate command wlcommand createstylehi WS OVERLAPPEDWINDOW WS_CLIPCHILDREN char wichar sziconname icon 1 y_coord 10 timer wltimer destroy wldestroy controll CONTROL szclassname BUTTON sztitlename 0K x_coord 20 y_coord 40 wwidth 30 wheight 20 hmenu IDOK cfeatestylehi WS CHILD WS VISIBLE createstylelo BS PUSHBUTTON CODE kickstart lea si windowl addr of window object call si make PASCAL si jmake the window lea si controll call si make PASCAL si smake child window ret oat PROC PASCAL LOCAL hdc WORD LOCAL paintstructa PAINTSTRUCT lea di paintstructa call BEGINPAINT PASCAL si hwnd ss di mov hdc ax call SELECTOBJECT PASCAL ax si hfont call TEXTOUT PASCAL hdc 10 20 cs OFFSET outstring 29 call ENDPAINT PASCAL si hwnd ss di ret outstring DB Click button for direct video wipaint ENDP wlcreate call GETSTOCKOBJECT PASCAL OEM FIXED FONT mov si hfont ax Feat T cmp WORD PTR si lparam O lo half 0 if a menu selection jne notmenu ret notmenu cmp si wparam IDOK button child window selected note that lo word of lparam has han
305. h AX OAOOh DS E SI selector offset of ASC11Z null terminated string which identifies the DPMI host vendor Returns if function successful CF clear ES E DI selector offset of extended API entry point and DX GS EAX ECX EDX ESI and EBP may be modified DPMI Services 399 if function unsuccessful set AX error code 8001 h unsupported function extension not found Int 31h Function 9B000h Set Debug Watchpoint eee Sets a debug watchpoint at the specified linear address Call with AX OBOOh BX CX linear address of watchpoint DL size of watchpoint 1 2 or 4 bytes DH type of watchpoint 0 execute 1 write 2 read write Returns if function successful CF clear BX watchpoint handle if function unsuccessful CF set AX error code 8016h to many breakpoints 8021h invalid value in DL or DH een 8035h invalid linear address linear address not mapped or alignment error Int 3ih Function 0BO1h Clear Debug Watchpoint Clears a debug watchpoint that was previously set une the Set Debug Watchpoint function Int 31 h Function OBOOh and releases the watchpoint handle Call with AX OBOlh iBX watchpoint handle Returns iif function successful CF clear iif function unsuccessful C set AX error code 8023h invalid handle iint 31h Function 0B02h Get State of Debug Watchpoint Returns the state of a debug watchpoint that was jpreviously se
306. h 2 SP 30h 2 SS Returns if function successful CF clear ES E DI selector offset of modified Real mode register data structure if function unsucessful CF set AX error 8012h linear memory unavailable stack 8013h physical memory unavailable stack 8014h backing store unavailable stack 8021 h invalid value CX too large Int 31 h Function 0302h Call Real Mode Procedure With IRET Frame Simulates a FAR CALL with flags pushed on the stack to a Real mode procedure The Real mode routine must return by executing an IRET instruction Call with AX 0302h BH flags Bit Signifiance 0 reserved for historical reason must be zero 1 7 reserved must be zero cx number of words to copy from Protected mode to real mode stack ES E DI _ selector offset of real mode register data structure in the following format Offset Length Contents 00h 4 DI or EDI 04h 4 SI or ESI 08h 4 BP or EBP OCh 4 reserved ignored 10h 4 BX or EB 14h 4 DX or EDX 18h 4 CX or ECX ICh 4 AX or EAX 20h 2 CPU status flags 22h 2 ES 24h 2 DS 26h 2 FS 28h 2 GS 2Ah 2 IP 2Ch 2 CS 2Eh 2 SP 30h 2 SS Returns if function successful CF clear ES E DI selector offset of modified Real mode register data structure if function unsuccessful set error code 8012h linear memory unavailable stack 8013h physical memory unavailable stack AX 80 14h backing store unavailable stack 8021 h invalid value CX to
307. h is a convenient place from which the VxD and WinApp can retrieve it IVT 60h is thus i not in conventional segment offset form How a WinApp This FLAT pointer is immediately usable by the VxD All that the amp VxD can VxD needs to do is get it out of the IVT access global Ordinary 16 bit or 32 bit Windows applications can also use the data FLAT pointer but they do need to obtain a ring 3 FLAT data selector The global data can then be accessed in this manner mov es flatr3selector FLAT data selector ring 3 mov ebx lpglobaldata FLAT linear pointer from _ ivt 60h mov es ebx GLOBAL 1 accessing a field of global struc The above code sample is not from the TSR it shows how a WinApp can access the global data where GLOBAL is a field of the global structure There are various ways to obtain a FLAT data selector One thing that you could do is make an alias of DS and then modify the base address in the descriptor Gf you can locate the LDT see Chapter 12 Another way is for the WinApp to go to ring 0 and call a VMM service to create a FLAT ring 3 data selector the service to call is GETAPPFLATDSALIAS O described in the DDK If you have a VxD as part of your system you can get it to call this function and pass the slector back to the WinApp A great advantage to using GETAPPFLATDSALIAS is that the returned selector is in the GDT and will thus continue to work across VMs This is not such an issue with Window
308. has entered a critical section and cannot respond to Save Video Register State Interrupt 2Fh Function 4005h A VM application calls this function when it has started critical section processing Call with Ax 4003h Return value This function has no return value Comments After the VM application enters the critical section the virtual display device postpones calling Save Video Register State for up to 1000ms or until the VM application calls Exit Critical Section Interrupt 2Fh Function 4004h whichever comes first If time elapses without the VM application calling Exit Critical Section the virtual display device reprograms the video hardware anyway and when its operation is complete calls Notify Foreground Switch Interrupt 2Fh Function 4002h in an attempt to reinitialize the application properly Interrupt 2Fh Function 4004h Exit Critical Section Notifies the virtual display device that a VM application has completed a critical section and can now respond to Save Video Register State Interrupt 2Fh Function 4005h A VM application calls this function when it has completed critical section processing Call with AX 4004h Return value This function has no return value Comments Calls to Exit Critical Section not preceded by a corresponding call to Enter Critical Section Interrupt 2Fh Function 4003h are ignored Interrupt 2Fh Function 4005h The Save Video Register State Notifies VM applications t
309. hat the virtual display device VDD requires access to the video hardware registers The VDD calls this function for example when preparing to copy the entire screen to the clipboard Call with AX 4005h Return value This function has no return value Comments The VDD calls this function only if the VM application has called Enable VM Assisted Save Restore Interrupt 2Fh Function 4000h VM applications that receive Save Video Register State must save any data necessary to restore the current video state and must return within 1000ms If the aoolication fails to return in time the virtual display device accesses the video hardware anyway After accessing the video hardware registers the VDD calls Restore Video Register State Interrupt 2Fh Function 4006h to notify the application that it can restore its video state The VDD calls Save Video Register State only at times when the hardware must be ireprogrammed for what are essentially brief and inonvisible operations For example the VDD does not call this function prior to calling iNotify A ee Switch Interrupt 2Fh JFunction 4001 h Interrupt 2Fh Function 4006h iRestore Video Register State Notifies a VM application that the irtual display device VDD has relinquished its access to the video registers The VM application should restore the video registers to my state necessary to continue uninterrupted foreground operation Call with 14x 4006h JR
310. hatever you displayed in text mode or whatever will be lost unless you save it in a buffer This is some video cleanup code prior to returning to Windows mov ax 4002h Note undocumented RESURRECTION int 2Fh is similar call REPAINTSCREEN PASCAL REPAINT SCREEN function 32 bit applications REPAINTSCREEN is a Windows function but you wont find it mentioned in Microsofts Software Development Kit SDK nor in most other places It is described in the Device Driver Development Kit DDK 3 x versions from Microsoft and is another one that Microsoft seems to want to maintain a low profile on In the latest set of MSDN CD ROMs January 1997 REPAINTSCREEN is mentioned only in the Library Archive CD ROM Although it is in the Windows library file USER EXE the other two are GDI EXE and KERNEL EXE located in WINDOWS SYSTEM directory you may not be able to simply call it as Ive shown above Later on when you see the whole program together youll see what I did to call it I am referring through most of this chapter to the 16 bit API DLLs Thirty two bit applications can by indirect means such as thunking see Chapter 8 or some kind of separate 16 and 32 bit programs that cooperate see Chapters 12 and 14 access the 16 bit API However many of the low level functions have been ported to the 32 bit DLLs except that linkage information is not provided in the IMPORT library see footnote below and page
311. have executed 44 Windows Assembly Language amp Systems Programming and the conditional jump instructions can be used to test the flags and jump accordingly Below is a summary of the conditional jump instructions JZ jump if previous result was 0 JNZ jump if previous result not 0 JGrea ter this means if the SIGNED difference is positive JAbove this means if the UNSIGNED difference is positive JLess this means if the SIGNED difference is negative JBelow this means if the UNSIGNED difference is negative JCarry assembles the same as JB Signed and unsigned compare When using these instructions you do not enter the part in italics Note that when comparing two values we need to distinguish between whether the values are unsigned or 2 s complement Here are simple examples ADD AX VAL1 JZ ZERORESULT jumps if previous result 0 zero flag a set CMP AX 56 compare instr JA ABOVE56 jumps if AX gt 56 Variations JNC placel jjumn if Carry flag 0 JE placel same as JZ Equal JAE placel unsigned jump if above or equal JBE placel unsigned jump if below or equal The ADD instruction given as an example above is explained a little further on Ditto for the CMP instruction Note that ZERORESULT ABOVES56 and place are code labels chosen to have meaningful names Addressing Modes Obviously the instructions of your program will be accessing registers and memory and the mecha
312. he DPMICALLBACK function acknowledges receipt of the WM_USER by beeping the loudspeaker Note that this beep occurs as soon as you press a key how can this be since youre in a DOSApp The answer is that the DPMI host as the real Windows kernel switches VMs on a time sliced basis and so flips over to the system VM periodically to do housekeeping including sending the waiting WM USER message to the callback function for the window Another issue with the Protected mode ISRs is reentrancy This is especially a problem with hardware interrupts that can come in at any time Upon entry to the ISR hardware interrupts are disabled but once you put in the STI instruction they can occur Note that you would also send an End Of Interrupt EOI signal to the interrupt controller chip to tell it that it is now allowed to send more interrupts this is done by the default handler if you chain to it You could argue to avoid the problem by leaving the interrupt flag clear but this should not be done for too long The same point applies to the EOI signal I did it by calling the original handler via INT 60 in the ISR reached via the IDT If you put in an STI and an EOI has been sent in the case of hardware interrupts think about reentrancy You may have to organize the data used by the ISR to be dynamic on the stack Im thinking in particular of the data register structure in which DPMI passes the Real mode registers to and from the P
313. he prolog is to set DS to the current applications data segment but this is easy as SS always points to it even while execution goes back to Windows That is after the application is first entered SS remains always unchanged and always pointing to the data segment After the prolog the stack looks like Figure 4 3 Figure 4 3 Stack after executing prolog Stack Pointer SP 1 Base Pointer BP register points here D old BP 1 return address This is what FAR the stack looks BP 6 lParam like at this point in the BP 10 program BP 12 gt message BP 14 hWnd see next page 104 Windows Assembly Language amp Systems Programming mov ax WORD PTR bp 12 get message number cmp ax WM_CREATE message received after qe Create CreateWindow is called emp ax WM_DESTROY message received if a window is closed je quitmessage cmp ax WM_PAINT message received if Windows has already redrawn any part of the window je paint emp ax WM_COMMAND any selection of the menu will jne notcommand the WM_COMMAND jmp menu message notcommand cmp ax WM_LBUTTONDOWN one of many mouse jne notlbutton messages jmp break notlbutton cmp ax WM_CHAR message that a key pressed je char Default handling of messages push WORD PTR bp 14 hWnd push WORD PTR bp 12 Message type push WORD PTR bp 10 wParam push WORD PTR bp 8 hi half of lParam push WORD PTR bp 6 low half of lParam call DEFWINDOWPR
314. he 386 One is built on top of the descriptor tables and the other called virtual 86 does away with the descriptor tables altogether What s wrong with segments Page tables and control registers Linear address CPU Architecture 29 PII look first at the one built on top of the desriptor tables From our program point of view it looks just like the segmentation mechanism with the GDT and LDTs The only difference is that the CPU secretly stores the segments in actual memory not in one contiguous chunk but all over the place as 4K pages Why go to this trouble The operating system has trouble bringing segments in and out of memory because they are all different sizes if a new segment is to be brought in space must be found for it but space released by a segment that has vacated its spot may not be the right size This is a real problem for the operating system and it ends up with lots of little unused gaps everywhere Inefficiency By transparently parcelling the segment up into lots of little pages all the same size and storing them wherever there is a space the mismatch of segment sizes is no longer a problem We know that a space vacated by a departing page will be exactly the right size to take a new page No problem Well there is one To achieve this more translation tables are required called page tables The CR registers are used to address these and the page tables are kept in memory just like the descri
315. he A pes et COMMAND COM COMMAND program is running Free a second one i DOS system Free Note the entire SHARE program 64K high memory DOS system is global Considering the Protected mode of the system VM Windows runs the WinApps at the linear address ranges 0000 0000 to OOOF FFFF 8050 0000 to 80FF FFFF The first region is below 1M wherever Windows can find some free RAM The second region may seem like an amazingly high memory range but remember that these are linear addresses and paging will map them into the available physical memory 346 Windows Assembly Language amp Systems Programming Reference sources 32 bit WinApps Reference books Accessing Physical memory from aVM 32 bit WinApp selectors You may well wonder where I got these addresses from the source is the Soft ICE W Users Manual The address ranges quoted here are what Windows 3 x currently uses or so Im led to believe but they are not guaranteed Incidentally Soft ICE W is a specialised Windows debugger for Enhanced mode only that is a resident program and can be popped up at any time It is about the only tool available for debugging virtual device drivers and similar tricky code It is sold by NuMega Corporation Specific information on Windows 95 addressing should be in the latest Soft ICE W manual and another reference is Inside Windows 95 by Adrian King Microsoft Press USA 1994 The system VM has ju
316. he INT 8 hardware interrupt The second generates continuous pulses that are used by the dynamic RAM refresh circuitry The third is general purpose and is most often used to produce tones on the loudspeaker since its output is connected physically to the loudspeaker to initialise and start hardware timer a mov al OB6h setup the mode of timer 2 out 43h al mov bx 0700h load the counter moy al bl out 42h al mov al bh out 42h al i AT in al 61h or al 3 out 61h al set bit 0 and 1 of port 61h The hardware timers used in the PC are 16 bit down counters that can be loaded with a value and then started Once started they count to zero and then either stop or automatically reload and count down again They can be programmed to produce a pulse at the output pin upon reaching zero or simply flip state which gives a square wave output In continuous mode their frequency obviously depends upon the value first loaded this has to be programmed to port 42h in two steps Bit O of port 61h starts and stops the timer It is important to note that once started the timer is completely independent of the CPU and will keep on going until an OUT to port 6 1h stops it Direct Hardware Access 247 is now running To turn it off al 61h clear bit 0 and 1 of port 61h al 0OFCh 61h al i You could arrange this code in your Windows application in whatever way is appropriate It illustrates the use of b
317. he functionality of WOWGlobalAlloc16 and WOWGlobalLock16 e WOWGlobalFreel6 Thunks to the 16 bit version of GlobalFree e WOWGlobalLockl6 Thunks to the 16 bit GlobalLock e WOWGlobalLockSizel6 Combines the functionality of WOWGlobalLock16 and GlobalSize e WOWGlobalUnlockl6 Thunks to 16 bit GlobalUnlock e WOWGlobalUnlockFreel6 Combines the functionality of WOWGlobalUnlock16 Q and WOWGlobalFree1 6 e WOWHandlel6 Maps a 32 bit handle to al6 bit handle e WOWHandle Maps al6 bit handle to a 32 bit handle More Win95 Improvements Device I O Control Windows 95 introduced DeviceloControl as a standardized channel for performing I O that is to communicate directly with virtual device drivers This is also the preferred way to access INT 21h services though very few are supported Software interrupts will crash a 32 bit application so Microsoft is trying to force you to do most low level and direct access to the hardware through device drivers Much wider usage of the tile I O functions is found in Windows 95 DOS programmers will know that the INT 2 lh file handling functions can also operate on device drivers That is a device driver can be opened a handle obtained the tile read from and written to and then closed The concept is alive and well in Windows 95 CreateFile is used to open a virtual device driver prior to using DeviceloControl and CloseHandle is used to close the driver
318. he message message So this is what constitutes a message wParam ENN IParam e message 16 bit number 32 bit WinApp 32 bits e wParam 16 bit number e Param 32 bit number wParam is 16 bits also hence the W word prefix Every message has two parameters attached to it wParam and lParam the latter being 32 bits hence the 1 prefix meaning long What these parameters contain depends upon the message The prefixes are just a convenient notation for labels so that we know what they represent see page 82 Note that for 32 bit applications these parameters are all 32 bits making the W and 1 rather confusing as these prefixes are still used Before we delve further in this direction here is the DEF file SKELETON DEF NAME SKELETON DESCRIPTION Hi there program EXETYPE WINDOWS STUB WINSTUB EXE CODE PRELOAD MOVEABLE DATA PRELOAD MOVEABLE MULTIPLE HEAPSIZE 1024 STACKSIZE 8192 EXPORTS SKELETONPROC Skeletonproc is the callback function referred to as WndProc in earlier notes This is where Windows sends messages to be processed An application can have a separate callback function for each window dialog box or control The Bare Bones 91 DOS stub I have explained various aspects of the DEF tile throughout this book so investigate via the index Some of the lines are self explanatory WINSTUB EXE is a program supplied by the software vendor that is i
319. ider this chapter to have important buiding block educational information Many modern compilers allow in line assembly and this is developed further in Chapter 6 I have gone through the above outline of products and versions and based this chapter on early tools as not everyone has access to the latest tools Also it is actually quite educational to analyse a Windows assembly language program written with an earlier assembler minus the high level features Having understood RC file DEF file The Bare Bones 89 exactly what is happening high level features can be introduced later for much more streamlined programs Source Files The next step is to w rite the application for which of course you use a text editor However it is no longer a case of producing a single ASM source file let call it SKELETON ASM The absolute minimum files required are e SKELETON ASM program source e SKELETON RC resource script e SKELETON MAK Make file e SKELETON DEF definition file Resource and Definition Files Resource RC and definition DEF files are produced by a text editor though you can get some help with special paint programs to generate the resource scripts Resource scripts describe the appearance of what is seen on the screen dialog boxes menus etc It can also store other information I wrote SKELETON RC directly using a text editor since it is a simple example The definition file defines
320. ies 32 bit applications http ftp Reference book Direct Hardware Access 235 Ordinal Coordinates USER EXE_ is a Dynamic Link Library and is a standard feature of Windows It has a heap of useful functions and the question naturally arises what are the other functions in USER EXE Furthermore where did I get that ordinal coordinate of 275 Each function in USER EXE or any DLL for that matter can be referenced by a unique ordinal coordinate You can find out all of the functions in a DLL and their ordinal coordinates by use of a utility program supplied with Microsoft C C called EXEHDR EXE or TDUMP EXE from Borland C Since you may not have access to this utility I have listed the output of EXEHDR EXE for many of the Windows DLLs and drivers see the Companion Disk The file on the disk has a comprehensive alphabetical list of functions with a short description where it is documented what DLL it belongs to and its ordinal coordinate Each device driver has built in functions that can be called also Thirty two bit applications are a problem Apart from crashing if you try to use a software interrupt the low level undocumented and many previously documented functions are not readily available Matt Pietrek arguably the Windows systems programming guru of gurus covers this problem in Dirty Little Secrets about Windows 95 on line at uni mannheim Se AneoLOnead a Nae update dirty html In this Web page
321. ifically not supported in Protected mode and which will fail are e INT 20h Terminate program e INT 25h Absolute disk read e INT 26h Absolute disk write e INT 27h Terminate and stay resident e INT 21h AH 00h OFh 10h 14h 15h 16h 21h 22h 23h 24h 27h 28h Terminate process Open file with FCB Close file with FCB Sequential read Sequential write Create tile with FCB Random read Random write Get file size Set relative record Random block read Random block write The following DOS INT 21h functions will work but will behave differently from Real mode DOS versions Hooking Protected or Real mode interrupts e AH 25h and 35h These functions set and get the Protected mode interrupt vector They can be used to hook hardware interrupts such as the timer or keyboard interrupt as well as to Set Get interrupt vector BIOS DOS Windows Services 201 hook software interrupts Except for INT 23h INT 24h and INT 1Ch software interrupts that are issued in Real mode are not reflected to Protected mode interrupt handlers However all hardware interrupts are reflected to Protected mode interrupt handlers before being reflected to Real mode e AH 38h Get country data This function returns a 34 byte buffer containing a doubleword DWORD call address at offset 12h that is used for case mapping The DWORD contains a Real mode address If you want to call the case mapping function you need to use the
322. iguration no dip switches on cards 194 Windows Assembly Language amp Systems Programming Postamble I have introduced PC hardware but so much remains to be explained I covered the keyboard interface and expansion bus but these are only samplers What about parallel and serial disk drive timer real time clock and other interfaces Some of these I do touch on in later chapters however this book will grow into something enormous if I try to cover everything I could cover these in the next edition though Let me know if you really like the idea Choice of keyboard interface and expansion bus serve as case studies so that you can see how the principles earlier in the chapter are applied BIOS DOS amp Windows Low Level What s in this chapter DOS BIOS INTs Services Preamble This chapter introduces the services available to the Windows programmer but from a viewpoint that you would expect of a book on assembly language I have covered two major aspects the DOS services and the Windows low level services This chapter gives an overview and the next chapter provides practical code We havent been so far away from the operating system in earlier chapters but now is the time to delve in further In this chapter I have particularly been concerned about the relationship between DOS and Windows We have a new Operating system running on top of DOS with the CPU in Protected mode how much of th
323. ile handle Multiple program instances All that has been done in Windows is generalise the concept so that a handle can be obtained for any object I am generalising the word object here as Windows literature uses other terms that are still objects but used in a particular context One that comes to mind is the device context this is also a handle to an object Just to elaborate with DOS you do a call to open a file or device and DOS returns a handle This handle is just a 16 bit number that you can use within the program to read or write the file Since it is possible to simultaneously open many files it is convenient to have these handles a unique one for each file to read write the one you want So a handle is an ID an identifier for that file device object or control In Windows programming just about every resource is referenced by a handle Even your program has a handle and indeed so too has each instance see below of your program Instances A fascinating aspect of Windows is that there can be multiple copies of an application running or at least residing in memory concurrently After all why not since this is a multitasking environment You can for example have two copies of your word processor executing simultaneously and you can jump between them In such a situation each copy would be an instance of the program The current instance refers to the one you are dealing with at this moment
324. ils the call In the debugging version of KERNEL32 DLL the code emits a trace diagnostic GetProcAddress kernel32 by id not supported Now lets think about this Since the undocumented functions arent exported by name you cant pass the name of a KERNEL32 function to GetProcAddress to get its entry point And GetProcAddress specifically refuses to let you pass it an ordinal value The Microsoft coder responsible for this abomination really didnt want people Andrew Schulman myself from calling these undocumented KERNEL32 functions Apparently the only way you can call these functions is if you have the magic KERNEL32 import library that Microsoft isnt supplying with the Win32 SDK Never fear As youll see later in the book I make extensive use of the KERNEL32 undocumented functions for good not evil With a little bit of work I was able to coerce the Visual C tools to create a KERNEL32 import library that contains these documentation challenged functions Appendix A contains information about these functions and an import library for them Page 208 lists some of these functions To and From Text Mode If you choose to use RESURRECTION to come back from text mode the screen will stay black and bits will be redrawn as you use Windows If you do want the entire Windows screen to be redrawn then REPAINTSCREEN is necessary There are various options for going to and fro between text and graphics modes apar
325. in another VM via the int 2F 1685h mechanism push es save working registers pushds a Aen pusha ee id 2 sti essential mov ax cs set DS CS mov ds ax i Si mov ax 3560h get current INT 60 vector address int 21h o a mov ax es is there a WinApp handler or ax lt bx pi jz done60 if not don t call it int 60h call WinApp done60 popa restore registers pop ds POP es foe iret return to other VM runtime2F entered when Windows loads with AX 1605h and when Windows unloads with AX 1606h detect when Windows loads and set a flag so that sruntime9 will be activated sti documentation says this req d cmp ax 1605h test if Win is loading jne notload cmp CX 0 this must always be 0 else error jne notunload mov cs winloaded 1 mov cCS winmode dl notload cmp ax 1606h test if Win is unloading jne notunload mov cs winloaded 0 notunload jmp DWORD PTR cs oldoffivt2F o0ld int 2F This is a very interesting extension to INT 2Fh Function 1605h is called by Windows when it first loads This enables DOS device drivers and TSRs to perform any necessary initialization It is important to follow the rules here by first enabling interrupts and then calling the old INT 2Fh vector The latter is because other drivers TSRs may have hooked the vector CX must have zero If you for any reason decide that Windows should not go ahead and load then put a non zero value into CX
326. in either Real or 16 bit Protected mode and PCI BIOS has done this via INT 1 Ah function Blh Table 7 2 Great you can call this from a Windows 3 x application and the CPU will not have to switch back to Real mode The PCI BIOS requires an entirely different set of routines for 32 bit Protected mode Table 7 2 PCI BIOS access Use MT 1 Ah AH B th like any other software interrupt 16 bit Protected mode ditto Virtual 86 mode ditto 32 bit Protected mode BIOS is scanned for a signature indicating presence of 32 bit BIOS and an entry point is located The services are accessed by a FAR CALL PCI summary Note that technically it is possible if you are writing a 32 bit application to get it to call the Real mode 16 bit Protected mode PCI BIOS services but this is starting to get too involved at this stage Here are some of the highlights of the PCI architecture Multiple independent PCI buses in the one PC e 32 bit data bus at up to 132M sec megabytes sec and 64 bit at up to 264M sec e Fully synchronous with CPU bus up to 33MHz e PCI connector can be mounted alongside an ISA EISA connector so either type can occupy that physical space on the motherboard chassis e Processor independent e Support for 64 bit addressing e Support for 5V and or 3 3V supply e Full multi master capability allowing any PCI master peer to peer access to any other PCI master target e Full auto conf
327. in window No you can make windows from anywhere in the message handling routines Nor are you limited to the one WINDOW structure You can declare sub classes which inherit the fields from WINDOW but with their own extra fields These sub classes can also override any of the parent classes fields It is time to peek further inside WINASMOOL INC WINMAIN WINASMOO INC has the job of hiding the red tape of a Windows program It must handle multiple instances of a program that is if you double click on the program icon more than once It must handle multiple windows within the one instance Any one window would have its own instance of the window structure or object as I did by creating window For a second window I could create an instance of WINDOW called window2 Program listing WinMain looks similar to code that you would find in a continues until conventional WinMain function with some curious page 771 differences Well look at the whole lot WINASMOO INC WINASMOO ASM gt WINASMOO EXE Windows 00 program remember that Windows funcs only preserve SI DI BP amp DS MODEL SMALL LOCALS oe e k turns on prefix for auto local name mangling Borland only These are Windows functions EXTRN UPDATEWINDOW FAR BEGINPAINT FAR EXTRN ENDPAINT FAR DEFWINDOWPROC FAR EXTRN POSTQUITMESSAGE FAR EXTRN REGISTERCLASS FAR GETSTOCKOBJECT FAR EXTRN CREATEWIN
328. ing O code and then call it The program is written as a 16 bit small model program hence the 286 and MODEL smart at the very start The ring 0 code is a function called RINGOFUNC and is in its own 32 bit segment in a separate file called HEAVEN ASM This file is assembled separately and linked with ASMRINGO ASMRINGO ASM gt ASMRINGO EXE Windows demo program xThais skeleton assembly language program has been written for Microsoft MASM v6 1 Or you could put this 286 MODEL SMALL MODEL SMALL 386 It is still a 16 bit seg but allows use of 32 bit regs EXTERN RINGOFUNC NEAR this is in HEAVEN ASM It is the ring0 code BE E Use ices tater ath Sel a beeen Gerla oes ial ane bn eased an he ener ASMDEMOPROC PROTO FAR PASCAL HWND WORD SWORD SDWORD ASMDEMOPROC PROC FAR PASCAL ihWnd HWND iMessage WORD iwParam SWORD ilParam SDWORD LOCAL dummy 5 WORD LOCAL hDC HDC LOCAL 3 PAINTSTRUCT mov ax imessage get message Cype IF ax WM CREATE message received after call xcreate CreateWindow function is called ELSEIF ax WM_DESTROY message if window is closed call xquitmessage posts WM_QUIT amp does cleanup ELSEIF ax WM_PAINT call xpaint ELSEIF ax WM_COMMAND any selection of the menu will call xmenu produce this message ELSEIF ax WM_LBUTTONDOWN one of many mouse messages 32 Bit Ring 0 295 call xlbutton ELSEIF ax WM_CHAR message that a ke
329. ing detail in Chapters 11 and 14 You can get a good overall idea of what the DPMI services do by examining Appendix C They provide the kind of services that the old Real mode DOS services dont that is services connected with the descriptor tables managing extended memory going between Real and Protected modes getting at real memory from Protected mode and getting at the CPU control registers I introduced some DOS services back on page 18 but they are primitive DPMI does a much more thorough job and is specially designed for the multitasking environment Host and Windows provides the DPMI services for our program to use so client the correct terminology is that Windows is the DPMI host while our program is the client INT 31h The DPMI services are available through INT 3 lh which is only INT 2Fh available in Protected mode DPMI provides INT 2Fh services to obtain information about DPMI these run in Protected or Real mode see Appendix C and Chapter 9 A DPMI host must be running to provide INT 3 lh services though note that Windows is not the only DPMI host Other DOS extenders and memory managers are also DPMI hosts For example 386Max is a superb memory manager and DPMI 0 9 host from Qualitas Corp that enables you to write DOS applications that can run in Protected INT 2Fh mode aoe The basic INT 2Fh services are a DPMI host 204 Windows Assembly Language amp Systems Programming INT 31h logical groups
330. installing the handler as outlined above we will also have to perform a jump from the VM running the DOSApp into the system VM Actually this is a qualified statement It is better to say that Standard mode cannot have V86 VMs or DOS VMs since it can by the DPMI host have multiple Protected mode VMs Windows however only runs the one VM in which all WinApps reside Intel s DPMI specification places some caveats upon function 0201h The address placed in CX must be a Real mode segment address not a selector Consequently the interrupt handler must reside in DOS memory below M or the client must allocate a Real mode callback address See functions 0100h and 0303h in Appendix C If the interrupt is a hardware interrupt the memory that the interrupt handler uses must be locked The Intel DPMI specification places these caveats upon function 0303h A descriptor may be allocated for each callback to hold the Real mode SS descriptor Real mode callbacks are a limited resource A client should use the Free Real Mode Callback Address function 0304h to release a callback that is no longer required The contents of the Real mode register data structure are not valid after the function call only at the time of the actual callback 280 Windows Assembly Language amp Systems Programming Handling hardware interrupts DOSAPP ASM A line of thought If the CPU happens to be in Protected mode when a hardware or software inter
331. interrupts in general since interrupts are tied in with how the keyboard interfaces to the computer I have introduced interrupts on page 33 and in further depth on page 250 Refer to the circuit of Figure 7 5 The keyboard scancode is routed to port A on the PPI chip when PB7 0 The address of port A is 60h port B is 61h port C is 62h etc The keyboard also generates an interrupt to the 8259 Interrupt Controller chip causing INT 9 With AT class PCs including most 386 486 and Pentium PCs we can still visualise the operation as following this pattern There are two microcontrollers an 8031 on the actual keyboard and an 8042 on the motherboard The latter implements the functionality of the original PPI with some changes For example port C 62h Scancodes INT 9 IRQ to IVT mapping PC Hardware 185 has completely fallen by the wayside The 8042 has itself been consumed into larger VLSI chips Figure 7 5 Keyboard interface Keyboard 8042 microcontroller on older AT class PCs Each key generates a unique scancode The keyboard outputs a scancode when a key is pressed and again when it is released and of course generates an interrupt each time The difference is determined by PA7 0 when pressed and PA7 1 when released Note that it is the job of the BIOS routine INT 9 to convert the keyboard scancode to ASCII and place it in the input buffer A small detail to keep in mind is that the keyboard int
332. ion Windows Termination Notification Device Call Out Windows Initialization Complete Notification Windows Begin Exit Release Current VM Time Slice Begin Critical Section End Critical Section Get Current Virtual Machine ID The specific reference for Appendix D is the Device Driver Adaptation Guide Microsoft Device Development Kit version 3 1 1992 Microsoft Corporation All rights reserved Reprinted with permission from Microsoft Corporation 401 402 Windows Assembly Language amp Systems Programming Function Description 4000h Enable VM Assisted Save Restore 4001h Notify Background Switch 4002h Notify Foreground Switch 4003h Enter Critical Section 4004h Exit Critical Section 4005h Save Video Register State 4006h Restore Video Register State 4007h Disable VM Assisted Save Restore INT 2F Extensions Detail Interrupt 2Fh Function 1600h Get Enhanced Mode Windows Installed State Determines whether 386 Enhanced mode Windows is running If a program intends to use a 386 Enhanced mode Windows function it must first use this function to make sure that 386 Enhanced mode Windows is running This function is valid under all versions of 386 Enhanced mode Windows Call with Ax 1600h Return value The return value is 00h or 80h in the AL register if 386 Enhanced mode Windows is not running If 386 Enhanced mode Windows is running the return value depends on the version of Windows Windows 386 versi
333. ion locks the segment into that linear address This is the only sure way to stop Windows from moving the segment and it works in both Standard and Enhanced modes However in Enhanced mode you can use GLOBALPAGELOCK to prevent paging and guarantee that the segment is locked into physical memory What these functions will do for you is speed up operation as the ISR s will be kept in memory and you wont lose what you write to the code segment They are not essential however What about getting at data in the data segment from inside the ISR No problem because you can store the value of DS in the code segment The data segment doesnt even have to be FIXED because its descriptor will be automatically updated unlike an alias None of this will work under Standard mode Why am I even bothering to discuss Standard mode its dead dead dead Maybe in some remote parts of the world there are still people running Windows in Standard mode I promise not to mention it again The Real Mode Handler Ok now for the DOS TSR interrupt handler Actually this is the most fascinating part of the exercise There is a bit of a myth that you shouldnt develop Windows aware DOS TSRs and device drivers but should instead be going for virtual device drivers The DOS driver has a lot going for it The fact that it takes up valuable RAM real estate in the first 1M is always brought up as a negative factor However this is not such a big issue
334. ion members or message methods that the WINDOW structure is initialized to As you can handling see they dont do much and if not overridden all you will get on the screen is a blank window It will have a system menu so you can quit the program and it can be minimized etc all of this functionality was set by REGISTERCLASSQ and CREATEWINDOW WINDOWdestroy call POSTQUITMESSAGE PASCAL 0 ret WINDOWcreate WINDOWpaint WINDOWcommand WINDOWLbuttondown WINDOWlbuttonup WINDOWchar WINDOWtimer WINDOWresize WINDOWmousemove WINDOWdefaultproc call DEFWINDOWPROC PASCAL si hwnd si wmessage si wparam si lparam ret Inheritance Example 00 The next example shows how to create a control You will need to program with refer to a Windows programming book to learn all about controls a control however this example will give you some idea A control is a child window that is a window that resides within the client area of the parent window and normally sends its messages to the callback function of the parent The example creates a simple button with the title OK inside it When the mouse is clicked over the button it disappears Pressing any key brings it back Not much but it does illustrate some useful principles Figure 6 2 shows what it looks like The button that is added by this program is the one on the main window The message box is also a type of child window created by MESSAGEBOX
335. ions in them These will run fine in both Windows 3 1 and 95 A 32 bit application will run in Windows if it has the Win32s library installed and it will run natively in Windows 95 So I guess we need to move ahead into the pure 32 bit world A lot of the material earlier in this book has focused on 16 bit code although the principles are in most cases applicable to 32 bit code also We need a chapter that elaborates on the differences in coding for 32 bit segments and Win32 the 32 bit Windows API library We also need to see a pure 32 bit application The next chapter does this Other chapters 13 32 Bit Ring 3 Preamble This book has been structured in a quasi historical sequence starting with 16 bit programming in the early chapters gradually introducing 32 bit issues in latter chapters I didnt want to dump 16 bit as it is still relevant and will remain an issue for a long time Even if a systems programmer wants to program entirely in 32 bit mode Windows 95 internally is surprisingly 16 bit oriented This means that a thorough knowledge of the 16 bit issues and the interaction between 16 and 32 bit modes is required Therefore the gradual progression of the chapters from a 16 bit foundation is most relevant Of course many developers are still programming for Windows 3 x and 16 bit applications run fine on Windows 95 and even have some advantages with regard to system privileges compared with 32 bit applications
336. ions prior to 6 00 The latest MASM requires modifications to the Make file refer page 125 though it can be made command line compatible with v5 1 Borland vs Borlands TASM is different again refer to page 124 because Microsoft TASM and TLINK have their own command line syntax Make Borland s MAKE EXE also has its own peculiar syntax requirements but note that the version supplied with C version 92 Windows Assembly Language amp Systems Programming Why use a Make fife 3 00 and later is supposed to be more compatible with NMAKE this is doubtful see my comments in Chapter 14 The Make file saves you the trouble of typing in all the assemble compile and link steps at the command line Some integrated environments generate the Make file automatically so you dont even have to do that much but there are some sound reasons for learning about and using Make files not the least of which is flexibility Some integrated environments generate what is called a project file which is saved with a special extension and with some products it is possible to convert a project tile into a Make file The fundamental difference in usage is that in the integrated environment you do everything via pull down menus while you run the Make file from the command line Programmers Microsofts Programmers Workbench PWB is an example of an Workbench PWB Exp anation of above Make file Within Windows integrated environmen
337. ircuitry looks like at the memory end Figure 7 3 Interface CPU to memory Detects the address range of the RAM AO Al9 chip so has the address bus higher order address bits as input CS means Chip Select MEMR MEMW data bus Address Decoder Basically a memory chip has a data bus an address bus chip select input s and read write control input s This example RAM Random Access Memory chip has an active low chip select line coming from an address decoder This decoder detects the presence on the address bus of the appropriate addresses for this particular memory chip this chip is being addressed it selects the memory chip Note that the address decoder itself has a CS chip select input ALE is connected to this It ensures that the address decoder only operates when there is a valid address on the address bus Assuming that the RAM is addressed correctly the CPU tells it via MEMR and MEMW which way the data is to go Notice that only Al7 to A19 go to the address decoder this is an example circuit only and specific circuits may differ from this but generally it is only necessary for some of the address lines to go to the decoder This is because the memory chip resides at a range of addresses the lower order address bits go directly to the chip to select a particular memory byte Get the idea The higher address lines select the chip while the lower lines select a particula
338. iret On the other hand if the ISR is not to chain to the old vector but instead is to return from whence it came the return address on the stack must be put in CS IP in the data structure cld lodsw get Real mode IP off stack mov es di ipl ax put it into IP in data structure lodsw get Real mode CS off stack mov es di csl ax put it into CS in data structure lodsw get Real mode flags mov es di flagsl ax put into flagsl in data structure add es di sp1 6 adjust SP on data structure iret The above mechanism is elaborated upon in Chapter 12 DPMI 1 0 This is all quite involved just to post a message from a DOSApp global to a WinApp but while I think of it if your need is not to signal or memory execute but just to share data DPMI version 1 0 does have a neat solution Ok this 1s academic as no versions of Windows run DPMI vl O but maybe one day DPMI version 1 0 not v0 9 has a function 0D00h Allocate Shared Memory that creates and allocates a memory block that is accessible across all WMs Thus all Windows and DOSApps have access to it There are also ODO1h Free Shared Memory 0D02h Serialize on Shared Memory and 0D03h Free Serialization on Shared Memory The latter two allow synchronization of access to the shared block Privilege levels 12 32 Bit Ring 0 Preamble As explained in Chapter 1 the 286 and 386 have four privilege levels numbered from 3 to 0 With Windows 3
339. is means that the data content is itself an address Earlier I defined ptr1 DW 789 but the treatment of the content 789 is up to the program Consider these examples call ptrl calls address pointed to call placel j calls placel Immediate versus NoN immediate mode CALL call ptr1 at execution time will not jump to the ptrl data in the data segment obviously that wouldn t make sense No since the CALL instruction has assembled as a non immediate addressing mode even though the operand of the instruction is the address ptrl the instruction looks at the content of ptrl and uses that Thus execution will transfer to offset 789 in the code wherever that is 60 Windows Assembly Language amp Systems Programming call place1 is here for comparison Again the operand will have the address of placel but the immediate addressing mode will cause execution to go to place Now I m going to be a little tricky I will redefine ptrl DATA l ptrl DW placel defining a pointer CODE call ptrl placel Always remember that as the assembler goes through the source code it simply replaces any data or code labels with the addresses they represent So where will the CALL instruction transfer execution to NEAR amp The above examples of pointers are jumps within the current code FAR segment so they are NEAR however pointers can also be FAR pointers This is discussed in Chapter 4 I have also made some ref
340. ite entire applications for Windows just in assembly language though it is more usual to restrict assembly to critical sections of the program Although theres no concrete argument against writing the whole thing in assembler its a matter of preference and personal requirements I will show that the argument that assembly programming is more tedious and time consuming than C is not true From the professionals point of view assembly gives very precise control over what is going on is more appropriate for low level and getting behind the scenes development and is potentially extremely compact and fast From the beginner point of view looking at how to write the entire program at the assembly level is most useful for learning purposes and gives us useful insights into how Windows works The argument in assembly language favour is developed further in the last chapter see page 367 85 86 Windows Assembly Language amp Systems Programming Organisation have organised this section by example with a simple Hi there of this chapter 32 bit skeleton application Microsoft SDK introductory program as shown on page 94 We go through it here step by step and put together the complete application This program is on the Companion Disk in directory SKELETN1 Note that I have written the program at the most fundamental level for instructional purposes However the next chapter introduces the same skeleton program but ma
341. ke file provided by Borland which is what I have done above It is not quite optimum as the resource compiler executes every time but at least it works I recommend that you use the B switch to force everything to build C gt make B DDEBUG There is something weird about Borlands MAKE EXE and I personally use NMAKE EXE mostly B32ZTOOLS Note also that Borland supplies B32TOOLS PIF I recommend PIF to that you put a shortcut to it from your Windows 95 desktop It has fine tune the the correct settings for the DOS box You will find it in DOS box C TASM BIN Also place C TASM BIN into the path statement of your AUTOEXEC BAT file so DOS can find the executables TLINK32 finds the library tile IMPORT32 without any help DEF file Finally the definition tile W32DEMO DEF NAME W3 2DEMO DESCRIPTION ASM program EXETYPE 32 bit Ring 3 317 WINDOWS STUB WINSTUB EXE CODE PRELOAD MOVEABLE DATA PRELOAD MOVEABLE MULTIPLE HEAPSIZE 8192 STACKSIZE 8192 EXPORTS ASMWNDPROC W32DEMO DEF is referenced by the second last parameter in the TLINK32 command line Tur bo If after assembling and linking it doesnt work it is time to use the Debugger debugger Stay in the DOS box to use it and type this C gt TD32 W32DEMO EXE A text editor IDE for use with TASM WAL K32 development suite for MASM Turbo Debugger has been an old favourite of mine Its really nice and very easy to use O
342. kes use of advanced assembler features so it is more practical The program of this chapter has the advantage that it represents the lowest common denominator and should work with just about any assembler I recommend that you use this chapter as a theoretical learning tool and focus hands on experimentation in the next chapter Chapter 13 describes a 32 bit skeleton program however I recommend that you follow the steps of the ladder of learning The 16 bit applications of this and the following chapter will work fine under Windows 95 By all means refer to Chapter 13 as you study this chapter and the next as you wish to see the contrast you will find the 32 bit code is structurally the same and very few changes are required to convert a 16 bit application Getting Started Tools Required So what do you need Many people will have access to the Microsoft Software Development Kit SDK and Microsoft assembler MASM so this is a good starting point In my previous book I showed how the SDK and MASM v5 1 could be used to write a complete assembly language program but I now consider v5 1 to be behind the times However I constrained the program in this chapter to work with v5 1 in which case the earliest tools that I can guarantee the program to successfully assemble and link with are in Table 4 1 Note that SLIBCEW and CWINS are C run time libraries and are not required for the skeleton However in a situation where you
343. ld switch the processor to virtual 8086 mode clear the carry flag and return If an error occurs the function sets the carry flag and returns However Windows ignores the carry flag so if an error occurs no action is taken and the processor is left in Real mode Whether an error occurs when enabling or disabling virtual 8086 mode it is unto the callback function to display any error message to the user Also the callback function must not enable interrupts unless an error occurs and the function sets the carry flag A device driver or TSR supplies a callback function by copying the address of the function to the DS SI register pair when it processes the Windows Initialization Notification Interrupt 2Fh Function 1605h Windows permits only one callback function so the device driver or TSR should first check to make sure that the DS and SI registers are both zero If they are nonzero the device driver or TSR should set the CX register to a nonzero value and return directing Windows to terminate without starting Initializing a Structure An MS DOS device driver or TSR initializes a Win3 86_Startup_Info_Struc structure to direct 386 Enhanced mode Windows to load the virtual device and to reserve the instance data the device driver or TSR needs to operate in the Windows environment The device driver or TSR is also responsible for establishing a chain Win386_Startup_Info_Struc of startup structures by copying the c
344. lds in the data structure are DWORDs so that 32 bit registers can be passed to Real mode Note however that 16 bit hosts are not required to pass the high word or 32 bit general registers or the FS and GS registers to Real mode The target Real mode handler must return with the stack in the same state as when it was called When this function returns the Real mode register data structure will contain the values that were returned by the Real mode interrupt handler What the above program does Calling a DOSApp Virtual Real mode Real Mode Access 27 What I have done here is called INT 16h AH 5 which puts a character into the old DOS keyboard buffer The character has to be provided in CX as scancode ascil All of the register values to be passed to Real mode have to be placed into an array pointed to by ES DI That s it The Real mode routine executes then returns To find out if the character really was placed in the buffer I then called INT 16h AH 0 which gets a character from the buffer and will hang if nothing is in the buffer Notice that I called this in the normal fashion this will go via the IDT and IVT as per normal The previous INT 16h AH 5 would have worked in this way also but I have used the DPMI service to show how to call code that is not necessarily a Standard BIOS or DOS service By this DPMI mechanism you can call any code below 1M with the CPU running in Real mode actuall
345. lers within this chapter The disadvantage of the non OOP version is that it is awkward cumbersome and verbose The OOP version is easier to use conceptually simpler and requires fewer lines of code Look on the Companion Disk for various example 00 programs A Skeleton Program You might like to recall how complicated and enormous was the skeleton from Chapter 5 Now here is the same thing WINASMOO ASM gt WINASMOO EXE INCLUDEWINDOWS INC INCLUDE WINASMOO INC Program Design 55 DATA windowl WINDOW szclassname WINASMOO sztitlename Main Window paint wlpaint create wicreate command wlcommand pete we eee CODE kickstart lea si windowl jaddr of window object call si make PASCAL si smake the window ret Praes wlpaint PROC PASCAL LOCAL hdc WORD LOCAL paintstructa PAINTSTRUCT lea di paintstructa call BEGINPAINT PASCAL si hwnd ss di mov hdc ax call SELECTOBJECT PASCAL ax si hfont call TEXTOUT PASCAL hdc 10 20 cs OFFSET sout 16 call ENDPAINT PASCAL si hwnd ss di ret sout DB Demo 00 Program wlpaint ENDP wlcreate call GETSTOCKOBJECT PASCAL OEM FIXED FONT mov si hfont ax ret Paras wlcommand cmp WORD PTR si lparam 0 lo half jne notmenu cmp si wparam 200 IDM QUIT Is Quit selected jne notquit call si destroy ret notquit cmp si wparam 201 IDM_ABOUT selected jne notabout call MESSAGEBOX PASCAL si hwnd cs OFFSET szmsg cs OFFSET
346. leton with the compiler set to generate assembly output see page 151 This listing is however substantially different from before PUBLIC SKELETONPROC SKELETONPROC PROC FAR The function is entered with far return addr 4 bytes lParam 4 wParam 2 message type 2 and window handle 2 bytes on the stack ret addr on top push ds This is some Standard preliminary pop ax ea aa of the registers nite bp it is called the prolog code push bp The Bare Bones 103 mov bp sp A push ds i mov ds ax sub sp 146 move the stack to a free region so as not to mess up the params Prolog code The above prolog code may seem strange It is at the start of all callbacks However the above code can be simplified if the application is never to run in Real mode A Windows application running in Real mode is only possible with Windows v3 0 and earlier and is an unlikely requirement these days Alternative simplified If the application will always be run in Protected mode prolog code the prolog can be simplified as follows push Py prolog mov psp set up stack frame push ds i save calling function s ds push ss move ss to ds local data segment pop ds 4 sub sp 146 reserve local data area An appropriate modification of the epilog code will also be required The simplified prolog is more suitable for explanation You can see that BP and DS are saved The main task of t
347. lication running in 16 bit segments and consider a very ordinary instruction that may appear in that program 58 POP Ax 6658 POP EAX This example is a typical unassembly showing address machine code in hex and assembly language mnemonic The first line contains no surprises the code 58h is the machine code for Pop ax a simple one byte instruction You would logically expect POP EAX to have a different machine code but note that the 58 is still there All the assembler does is insert an instruction prefix of value 66h The 66h prefix is an operand size prefix which tells the CPU to execute the following instruction in the opposite mode than it is currently in So the same 58h is used for both pops but the prefix determines the size of the pop There is also another type of size prefix the address size prefix of value 67h that overrides the current address size mode Therefore even though you are programming in a 16 bit segment you can use the 32 bit registers the assembler will insert the prefix in front of any such instructions Note though that the prefix overrides the default segment size but only for the current instruction When I first had to tackle this problem I was using Microsoft s Codeview debugger version 4 01 In my program I had the instruction POP EAX but when the debugger unassembled my program it showed POP AX This caused me enormous confusion until I realised that
348. lid selector Int 31h Function 0007h Set Segment Base Address Sets the 32 bit linear base address field in the LDT descriptor for the specified segment Call with AX 0007h BX selector CX DX 32 bit linear base address of segment Returns if function successful C clear if function unsuccessful set AX error code 8022h invalid selector 8025h invalid linear address changing the base would cause the descriptor to reference a linear address range outside that allowed for DPMI clients Int 31h Function 0008h Set Segment Limit Sets the limit field in the LDT descriptor for the specified segment Call with AX 0008h BX selector CX DX 32 bit segment limit Returns if function seccessful CF clear if function unsuccessful C set AX error code 8021 h invalid value CX lt gt 0on a 16 bit DPMI host or the limit is greater than 1 MB but the low 12 bits are not set 8022h invalid selector 8025h invalid linear address changing the limit would cause the descriptor to reference a linear address range outside that allowed for DPMI clients Int 31 h Function 0009h Set Descriptor Access Rights Modifies the access rights and type fields in the LDT descriptor for the specified segment Call with AX 0009h BX selector CL access rights type byte CH 80386 extended access rights type byte Returns if function successful CF clear if function unsuccessful CF set
349. ling conventions You have had a first exposure to them in the above listing What I m talking about are the prefixes to the parameters These are put there to clarify the type of data the parameter represents It would be breaking the flow of the explanation to describe this in detail but the prefixes used above are h to signify type of handle and Ip to signify long pointer A more complete list of prefixes and data types is given on page 82 Message Loop The WinMain function contains what we refer to as the message loop Looking at the above listing it commences with declarations of the passed parameters and their data types A little further down yov ll see GetMessage This is the one I ve been talking about it goes back to Windows and waits for a message Whenever a message is available on the queue and also whenever Windows decides the time is appropriate control will return to your program with the message Opening Windows 79 TranslateMessage is specifically for converting keyboard messages into a more usable form It is possible for more processing to be done but usually nothing much more happens and strange though it may seem the next function DispatchMessage sends the message straight back to Windows Callback Windows then calls another part of your program named function WndProc that we know as the callback function see below It is this function that finally does
350. ling this flag PUSHF and POPF which push and pop the flags register respectively If POPF is executed whatever value is on top of the stack will be popped into the flags register thus affecting IF IN OUT CLI STI PUSHF and POPF all work without question under DOS in Real mode However in Protected mode since the application doesnt have permission to do I O execution of any of the above causes an exception which is a special reserved interrupt that causes a Windows exception handler to execute It is the hardware in the CPU that does this detection The Windows exception handler may allow the IN OUT CLI STI and PUSHF to go ahead with due regard for contention with other applications but it modifies the POPF instruction so that it does not change the interrupt flag IF The moral of this story is never use POPF to change the interrupt flag There are many caveats to I O under Windows Yes its fine in Real mode It may also be tine in virtual 86 mode i e running in a DOS box inside Windows Note that some references call virtual 86 mode Real mode though it is really a Protected mode simulating the real Real mode Interrupts and IN OUT to most of the ports is allowed for WinApps in Windows 3 0 and 3 1 It works for 16 bit WinApps in Windows 95 also The problem is 32 bit WinApps I recently read this nice submission to the comp os ms windows programmer win32 newsgroup from Eugine Nechamkin gt I require to be abl
351. lncwatt sca neetieegaiiaee Pee eoret swam ees 223 Memory Mapped Files eceeeeee cere eee e een eees 224 POStamble sisceeciesevehicenceieav es Naime dese aera a 224 Direct Hardware Access 225 Preamble oda tasers Shaya ie awns an wee ed oewirioes ee Sees 225 Initalisation srein xe 465503 Sos Geen ss ee SP tena wees 226 Addressing Segments s sesessesssosoeososesesserees 227 Direct VideO esie aeea eles ea IAA eE AS 229 Restore Video es esesoreesseserosesersesesreerses 23 1 Change Video Mode ssdseisrcrerrisaren esris sui 232 A Direct Video Text Mode Routine 232 Call REPAINTSGREENO kucam a 234 Ordinal Coordinates sia nEs EEEE anes 235 To and From Text Mode sesssossessesesrensereeree 236 Video Output Issues sssesssesrssosserorrsrrerses 237 Message Input ccc cece eee e cence cence 238 Experimenting ccd0toxuigaenigh eee toss ers CARTEA 239 A Direct Video Window Program eseeees 239 DO POrtse 2 acca v innate keds oki cael eaiearness 244 Real Time Events 249 Preamble suk bssteneSestcesne a a aaa a 249 TORS orei kos ina Pin P Ga Me E ET 250 Hooking Vector siscpacaduncinadseciadleeen cans 251 Service Routine ISR sie wctsncadsedca deter sess e aes 253 Testing Saalbach ine bine ene e awe ete ad EEE 255 Hardware Interrupts ceeree seer cere eee e eet eeeeaee 256 XT Hardware Interrupts sxsacsasced icra hoscaeees 256 AT Hardware Interrupts seee scene tere eee eens 257
352. lopment that ended up in the first edition of this book was on Windows 3 0 while for this edition I worked mostly on 3 1 and 95 Some descriptions in this book will be more appropriate to 3 x than 95 I have tried to be clear on what target environment Im writing about You will find that the 16 bit code in this chapter works fine in Windows 95 The structure of this chapter is in two halves the first focuses on interrupt handlers for DOS and Windows and the second focuses on the transition between DOS and Windows the smooth transfer of control and communication between TSRs WinApps and VxDs Interrupt Handlers Chapters 10 and 11 give the elements required for interrupt handlers and I have put various example programs on the Companion Disk This section develops the topic further DOS Win Transitions 321 An interrupt handler that must work regardless of whether the computer is running a DOSApp or a WinApp requires a number of special considerations Rather than list complete example programs that go on for many pages I have given only partial listings here and focused on discussion of the various issues Chapter 10 shows a Protected mode ISR invoked from a WinApp running in Protected mode That is the software or hardware interrupt occurred while the CPU was in Protected mode This is the easiest case If the CPU is in Real mode at the time of the hardware or software interrupt and you want to pass control up to a Pro
353. low direct manipulation of LDT GDT and page tables However one other thing you might want to do is call the functions in the Virtual Machine Manager VMM which you can think of as the core of Windows and the functions in the Virtual Device Drivers VxDs Conceptually you can view Windows as having two APIs the ones you know abvut and that are described in all the Windows programming books and in the SDK and another set that can only be called by VxDs The latter functions are inside the VMM and the VxDs and are ring O code The conventional wisdom is that you must write a VxD to be able to call them but in fact our RINGOFUNC can do so The requirement simply is that you must be in ring 0 and you must be in the FLAT memory model The program developed so far falls down on the latter point One little note while I think of it I used GLOBALPAGELOCK a Windows API function to lock the entire code segment of ASMRINGO which means that it cannot be paged out and remains at the same linear and physical address There are advantages to locking a segment but one disadvantage is that Windows 3 1 tends to shift the segment down below 1M physical before locking it which ties up some of that valuable conventional memory Fortunately Windows 95 does not move it down below 1M If you write code that computes a certain linear address you want to be sure that it stays at that linear address Normally when you 32
354. lps a little bit Also I think that some of the linkages need to be shown For example it has to be clearer what variables belong to what code and if a code module is attached to an on screen object the relationship should be clearly shown That is the structure of everything in the program links and relationships should all be clearly and visually viewable It has some rough edges but it is a VPL and quite a good one It belongs to the very exclusive club of VPLs that completely avoid the necessity of having to write lines of code However like LabView you can drop down to code if required Layout is marketed as a mass market full cycle CASE tool for Windows and DOS program development This is in contrast to LabView Layout is not just a front end or back end CASE tool it is full cycle and directly generates very efficient EXE files or C or C output I suppose LabView can be used as a full cycle CASE tool but it is not a mass market tool Layout is what you would use to develop a product that is optimised to work with Windows utilises Windows features to the full extent such as OLE DDE and networking though note that LabView also supports DDE and TCP IP and generates very fast and small code Even though Layout was developed first for DOS it followed the Windows event driven style In fact it mimicked Windows in just about every way so it was a natural contender for conversion to Windows Advanced Systems
355. ls that we need to use Have a look at each one first then we ll go ahead and put it together into a working program Objects Borland s latest assembler is described as object oriented and there are various C compilers around There is also Turbo Pascal with Objects So what are they You ll find a chapter on object oriented assembly language later see page 137 but for now consider just a basic idea Whatever you can lump together as a whole as a distinct entity think of as being an object Your application s window is an entity on its own separate from other windows it is an object In fact so too are the distinct elements of that window such as the various controls the menu bar and the client area where you output text and or graphics to You can consider these latter objects as being children of or related to the parent window and subject to its dictates though there are limits as Windows is not a true object oriented environment Furthermore you access any object by getting its handle As you ll see in the skeleton even writing text to the screen requires you to get a handle for the client area Handles A handle is just an ID a unique number that our program can use to access the object Actually you probably already have some exposure to the concept Various PC programming books discuss handles in relation to file access under DOS 76 Windows Assembly Language amp Systems Programming DOS f
356. lues before returning The only exceptions to this rule are changes made to the BX CX DS ES and SI registers as a result of following the previous procedure Enable Disable Virtual 8086 Mode Callback Function Some device drivers and TSRs such as expanded memory emulators switch the processor to virtual 8086 mode Because 386 Enhanced mode Windows cannot _ start successfully while the processor is in this mode any device driver or TSR that switches to virtual 8086 mode must either switch back to Real mode or supply the address of a callback function that can switch between real and virtual 8086 modes Windows uses the callback function to disable virtual 8086 mode before Windows itself enters Protected mode Windows calls the callback function again to enable virtual 8086 mode after Windows exits Protected mode Windows calls the callback function using a far call instruction and it specifies which action to take by setting the AX register to 0 or 1 To disable virtual 8086 mode Windows sets the AX register to 0 disables interrupts and calls the callback function The function should switch the processor to Real mode clear the carry flag to indicate success and return If an error occurs the function sets the carry flag and returns Windows checks the carry flag and terminates if it is set To enable virtual 8086 mode Windows set the AX register to 1 disables interrupts and calls the callback function The function shou
357. lways passes THIS on the stack last parameter so that the called function knows which object it is dealing with Notice that in the PROC declaration I gave the passed THIS parameter the same name in practise you would have to use a different name because the assembler will object to one of its keywords being used as a label Early Binding The first call in the above listing is an example of early binding Why Because I have hard coded the address of the function I want to call into the CALL instruction in this case textoutmain A warning here though is that if your instances are LOCAL and if you use a memory model in which data and stack segments are different then there are potential problems with using SI A memory access to the stack segment requires BP relative addressing or an SS override if using SI It is possible for the object to be located in some other segment entirely and in that case THIS would have to equate to a FAR address such as ES S1 This comment does not apply to 32 bit programming which uses a FLAT memory model in which there is only one segment 142 Windows Assembly Language amp Systems Programming This will be an immediate mode instruction and is fast but it is a deviation from pure 00 principles C t will normally compile a C program into calls having early binding except for the case where the call is to take polymorphism into account Look at the rest of the line I pa
358. ly programmable and has its own configuration memory that most importantly is independent of the main memory and I O map With PC systems the standardized method of accessing the configuration memory of a PCI chip is by two reserved 32 bit I O ports OCF8h and OCFCh The former is used for addressing a location in configuration memory and the latter for reading writing 1t The former OCF8h is called CONFIG_ADDRESS and the latter OCFCh is called CONFIG DATA It is important to know that these two ports can allow you to access the configuration memory on any of the PCI interface chips 192 Windows Assembly Language amp Systems Programming on any adaptor card The 32 bit data that you write to CONFIG_ADDRESS is formatted as in Figure 7 8 Figure 7 8 CONFIG_ADDRESS write format 11 10 87 Function Register Enable CONFIG DATA Translation Type PCI BIOS extension Reference source Protected mode PCI BIOS Bit 3 1 has to be set otherwise the OUT instruction is treated like a normal I O operation not accessing the PCI bridge chip Bus is for use in systems with multiple PCI buses Device selects a particular adaptor card Function selects a function that the card understands and Register selects a register in the configuration memory An OUT to CONFIG_ADDRESS would be followed by an IN or OUT to CONFIG_ DATA Fortunately a BIOS extension has been defined to give programmers a slightly less hardware depen
359. ly time critical Reserved High Boost Reserved do not use Reserved_Low_ Boost Reserved do not use Time_Critical Boost Events that must be processed even when another VM is in a critical section should use this boost For example VPICD uses this when simulating hardware interrupts ES DI CallBack Points to the callback function Return value The return value is a cleared carry flag if successful Otherwise the function sets the carry flag and sets the AX register to one of the following error values Value Meaning 000 1 h Invalid VM ID 0002h Invalid priority boost 0003h Invalid flags Comments Windows calls the callback function as soon as the conditions specified by the Flags parameter are met This may be before or after Switch VMs and Callback returns The callback function can carry out any action but must save and restore all registers it modifies The function must execute an iret instruction to return to Windows The priority for the virtual machine remains at the level specified by Priority until the callback function executes the iret instruction Interrupt 2Fh Function 1686h See Appendix C Interrupt 2Fh Function 1687h See Appendix C Interrupt 2Fh Function 168Bh Set Focus This information is missing from the DDK A TSR uses this function to force the input focus to a given VM This service has some inherent risks The function has the following syntax mov ax 168Bh set focus mov bx VMI d 0
360. m Make Borland vs Microsoft MAKE EXE Make file Make file why use it Mangled names MASM assembling amp linking MASM version 5 1 MASM version 5 2 MASM version 6 00 MASM vs TASM label scope MASM6 versus TASM3 MASM6 versus TASM5 MEMMANINFO Q Memory management Memory map of the PC Memory mapped tiles MEMORYREAD MEMORY WRITE MEMR W signals Menu item selection Message format Message loop MESSAGEBOX Methods objects Modeule32First MODULEFINDHANDLE MODULEFINDNAME 213 MODULEFIRST 213 MODULENEXT Q 213 Mouse driver functions 216 MOV instruction 45 MOVSx instruction 49 MSDOS SYS 2 MSGSTRUCT structure 65 114 MUL instruction 53 N Name mangling 151 NEAR amp FAR 41 42 NEAR CALL 4 NEG instruction 52 NetBIOS interrupts 202 NETBIOSCALLO 211 NOT instruction 55 NOTIFYREGISTER 214 NOTIFYUNREGISTER 214 Number systems 6 0 Object instance 66 138 Object oriented programming 66 137 153 Object pointer 139 Object window 00 program 153 OFFSET override 59 OOP overhead 175 OOP rationale for 137 OOP what is it 66 138 OR instruction 54 Order of storage of data in memory 64 Ordinal coordinates 235 OUT instruction 184 OUTPUTDEBUGSTRING 211 P Page tables amp Control registers 29 Paging 28 Paragraph addresses 30 Pascal calling convention 78 113 PASCAL qualifier 113 PCI bus 191 PEEKMESSAGEQ 211 238 Pointers 59 139 Polymorphism 14 POP instruction 39 POPF instruction 31 245 Po
361. member TEXTOUTO belonging to class WINDOW can be written in in line assembly code with data members fully accessable THIS is also available to the assembly code and I have put it into SI for convenient usage Note that I preceded each line with the asm keyword however it is also allowed to have a single asm keyword followed by an opening brace and then multiple lines of assembly code not requiring the asm keyword terminating with a closing Static versus have shown two ways of creating the instance windowl The automatic instances What the above program does commented out example is static because it is outside main while the other is automatic because it is created on the stack for the duration of execution within the function See how I have addressed the data member active from assembly code Actually this is dependent upon memory model and whether the object is static or automatic For the SMALL and FLAT model the SS and DS registers are the same so there is no problem For those models in which SS and DS may be different the code given here would be ok for a static object but SS override will be required for automatic data This can be taken care of by using BP instead of SI since BP by default references the stack segment By the way the above program passes the value 07 to TEXTOUT which sends it to the screen 07 is the bell character so you get a beep to indicate success
362. memory responds by putting the data on the data bus and the CPU reads what is on the data bus near the end of the cycle the exact moment when the CPU reads the data bus is when MEMR goes high Figure 7 1 CPU bus showing some of the control signals Address bus 20 bits for 8088 6 3 bits for Betts 32 bits for 80386 Data bus 8 bits for 8088 y bits for 8086 amp 80286 32 bits for 80386 Control bus INTA Interrupt Acknowledge IOR VO Read IOW I O Write Dad MEMR Memory Read MEMW Memory Write These are control signals ALE Address Latch Enable from the CPU amp maybe via sector aoe NOTE associated i There The appended to some are also signa other way CPU and associated chips s going the signal names indicates they are low active Start of machine cycle i End of machine cycle a machine cycle corres Time gt ponds to one or more clock CPU puts an address on address bus Aad oo upon CPU puts ALE low while address valid Valid data on data bus Data bus to or from the CPU Or neither if this is a MEMR or MEMW pulsed low null cycle 182 Windows Assembly Language amp Systems Programming There is still a loose end to the above description How does memory determine which data to put on the data bus The CPU is sending out an address asking for the data at a particular memory location Figure 7 3 shows what the c
363. ming cecccseecceeee ees 359 Disadvantages of LabView 0 0c cece 360 Integration with Assembly 0 00ee 362 Layout Programming cccecceccuceeeeeeeeaes 363 Comparison with LabView 0c0ceeee 364 Integrating with Assembly 0005 365 Assembly versus High Level Languages 367 Instruction Summary 369 Keyboard Tables 379 Witte CYSu accu siwdeacwaleowaausowetoustea aT 379 Extended ANST gc vecmro se loheneca EASA 382 IBM ASCII 4 06 outs con a eit kaweoneae nono vane cn eau 383 DPMI Services 385 DPMI INT 31h Functions Listed by Functional Group 385 DPMI Services Detail 0 cece cece cece ees 389 INT 2F Extensions 401 INT 2F Extensions Detail 0 c cece eee eens 403 Index 413 Product amp Publication References 005 419 PEOPLE ratako aA neue maak r ene eea 419 CPU Architecture Structure of the first two chapters A study method x86 family compatibility Preamble This chapter starts off from when a PC is first turned on and I have assumed only a basic familiarity with computer principles The focus is on the architecture of the CPU that is how the processor itself works Chapter 2 takes the next step by introducing the instruction set the machine instructions that the processor understands I have structured the material like a ladder from a very basic level so feel
364. miters For example mov ax vall moves vall into AX e But also note that you do not use the to separate in line statements not even the last one The ASM Stub Object If you refer back to the program listing in the section C pointer Binding on page 142 you will see the creation of an instance window1 and the use of a pointer ptr to implement late binding Recapitulating WINDOW ptr ptr amp windowl ptr gt TEXTOUT vall val2 So that you are absolutely clear on what this compiles down to here is the actual assembly language generated Program Design 51 mov si OFFSET windowl mov ax val2 notice the order of pushing push ax mov ax vall push ax push si notice that THIS pushed last mov bx sit4 74 is the offset of the pointer to call bx TEXTOUT in object windowl Looking back again atthe code from C Binding on page 142 you will see the definition of TEXTOUTO But if TEXTOUT is to be the assembly language module you would leave it in the C program for now as a stub You would put in the skeleton code as follows void WINDOW TEXTOUT int vall int val2 int x boxl draw 1 2 member of another object this gt dosomething nypothetical function x active data of current object Calling a This code shows various ways of getting at data Dosomething is member an example of calling a function member belonging to the current current object though I
365. more addresses programs designed to directly manipulate segment registers can do are back so The CPU does compute a 20 bit address consisting of Virtual paragraph address plus offset but this is not put on the external address bus Instead it is processed via page tables that is translated to some other 32 bit address then put onto the address bus Once again this paging is transparent to the programmer but it does mean that the program data etc are not where you think them to be judging from the segment registers Virtual 86 mode is useful not just for emulating the old XT machine computer but is the very foundation of Windows Enhanced mode True each virtual machine will have an addressing limit of 1M but Windows can create many of these Figure 1 14 Figure 1 14 Virtual Real mode VIRTUAL XT PC ent 1M address space fis gt ayes l Virtual XT PC Virtual XT PC The upper 8 Instead of putting the 20 bit linear address onto the address bus as bits of the for Real mode virtual 86 mode uses the upper 8 bits of this linear address are address as a lookup in the current page table note that the table entry contains the base address of the page which is combined with the lower 12 bits of the linear address to form the actual remapped 32 bit address It is this final 32 bit address that the CPU puts out for a memory access Refer also to page 274 Figure 11 2 Four
366. mory area The first 64K of extended memory is sometimes referred to as high memory The map in Figure 1 4 is a rough indication of how everything looks When Windows has loaded however the processor will be in what is called Protected mode Chapter 12 goes a lot more into the particular complications of Protected mode in which the basic memory map in Figure 1 4 can no longer be considered as residing at the actual physical address range zero to 1M The 386 is capable of creating virtual machines each with an apparent 1M address space Note that the addresses in these virtual machines are called virtual addresses Unfortunately the PC is a mess It started out life in 1980 with a text only screen cassette mass storage no hard disk no real time clock only 64K of RAM and an 8088 CPU Features got tacked on over the years and the operating system and hardware grew and grew One of the most fundamental problems inherited from the 8088 and something that causes headaches for programmers now is segments Segments Popular desktop PCs prior to IBM s PC used 8 bit processors such as Intel s 8008 and Zilog s Z80 Figure 1 6 They have an 8 bit wide data bus while the 8088 introduced the 16 bit architecture Although the 8088 has only 16 bit data paths internally with an external data bus of 8 bits The 8086 is identical to the 8088 except it has a full external 16 bit data bus The earlier 8 bit CPUs had 16 bit address b
367. mouse activity on your application s window for example that Windows determines will affect your program will result in the generation of an appropriate message Windows is always working seeing everything that happens Structure Of Below is the application s main function entered from Windows WinMaing when the program starts executing It is called WinMainQ and I ve used C syntax straight from the textbooks int PASCAL FAR WinMain hInstance hPrevInstance 1pCmdLine nCmdShow HANDLE hInstance current instance HANDLE hPrevinstance previous inst LPSTR 1lpCmdLine command line ptr int nCmdShow show type initialization lt instance handling create and display a window aa GetMessage amp msg NULL NULL NULL Trans lateMessage amp msg DispatchMessage amp msg 32 bit The above code is ok for a 32 bit application as well as a 16 bit differences application One difference is the size of the parameters passed to WinMain see Table 3 1 A 32 bit application does not have to worry about hPrevInstance Also a 32 bit application does not have to name its first entry point WinMain but we can continue to do this as a convention Also as explained below and on page 3 14 the Pascal calling convention is only applicable to 16 bit applications 78 Windows Assembly Language amp Systems Programming Pascal calling convention STDCALL calling convention D
368. mov bx cs and bx OFFF8h get offset in ldt mov ax es bx get size of segment mov cssize ax mov ax es bx 2 get lo half of lin addr mov WORD PTR flatlin ax mov al es bx 4 get hi half of lin addr mov ah es bx 7 mov WORD PTR flatlin 2 ax calculate FLAT linear address of ringOfunc mov ax WORD PTR flatlin add ax ring0func note OFFSET is optional jnc moppi mov bx WORD PTR flatlin 2 302 Windows Assembly Language amp Systems Programming inc bX mov WORD PTR flatlin 2 bx moppi mov WORD PTR flatlin ax create callgate to ringOfunc push es invoke ALLOCSELECTOR O j create a descriptor in ldt pop es cmp ax 0 je selectorerror mov vringO cs ax save final selector and ax O0OFFF8h get offset of descriptor in ldt mov bx ax mov ax WORD PTR flatlin my ring0 linear address mov es bx ax mov ax WORD PTR latlin 2 i mov es bx 6 ax mov WORD PTR es bx 2 28h FLAT code selector in gdt mov BYTE PTR es bx 4 0 04 2dwords copied to stack mov BYTE PTR es bx 5 11101100b present 1 dpl 3 app 00 type C type C 386 callgate find the FLAT linear address of this program s data segment mov bx ds and bx 0FFF8h get offset in ldt mov ax es bx 2 get lo half of lin addr mov WORD PTR flatdatalin ax mov al es bx 4 get ree of lin addr mov ah es bx 7 mov WORD PTR flatdatalin 2 ax qwert jmp SHORT qwerty lockfailed jee put in handlers
369. mp Systems Programming NetBIOS interrupts Accessing BIOS DOS from Protected mode More vagueness Windows also supports the DOS NetBIOS interrupts The Developers Notes advise that all of the network control blocks NCBs and buffers must reside in fixed memory that is page locked Also all code that calls NetBIOS directly should reside in a DLL to ease the porting of the application to other operating environments I havent written anything more about NetBIOS support in this book If you want more information go to the Device Driver Developer Kit DDK Earlier in the book pages 33 I explained about the Interrupt Vector Table IVT used by Real mode interrupts and the Interrupt Descriptor Table IDT used in Protected mode I explained that Windows has in some cases provided alternative services via the IDT where necessary but in many cases the vector in the IDT points to a handler that changes the CPU to Real mode virtual 86 actually and calls the Real mode service as pointed to by the IVT This mechanism is shown diagrammatically on page 268 The Developers Notes say that Windows provides support for all MS DOS interrupts other than those specifically blacklisted above Despite the above comment heed the warning from Guide to Programming SDK 3 O manual you should use interrupts with extreme caution and only when necessary The SDK documentation leaves you hanging on the cliff at that point th
370. mp the start of the TSR use the Dump command then enter a new value somewhere Enter command and you will find the same new value showing up in the other DOS window Note that DEBUG is a standard DOS program and DRDOS also has a program almost equivalent to DEBUG I do have a modified DEBUG that will run on any version of DOS but at this stage I don t have permission from Microsoft to put it on the Companion Disk You may be able to locate a similar modified DEBUG on the Internet Usage of DEBUG is described in many DOS programming books Real Mode Access 2 77 A DOS application can call the DOS TSR by a software interrupt but since the DOS TSR is running in Real mode how does it communicate with a Protected mode WinApp Reference Walter Oney has solved this particular problem in Using DPMI to source Hook Interrupts in Windows 3 Dr Dobb s Journal February 1992 page 16 He does not tackle hardware interrupts his focus is purely on the issue of passing a message from a DOSApp to a WinApp across VMs Mechanism lt A DOS TSR can be made to load into the system VM only by for forwarding specifying it in WINSTART BAT however what we want is to up toa hook an IVT vector that will appear in all VMs The reason for WinApp this is that we want a mechanism for a DOSApp in any VM to be able to find out the address of a forwarding routine in the DOS TSR in the system VM Did I just say that we want the TSR
371. n VK_CANCEL 3 Cancel key VK_MBUTTON 4 Middle mouse button 5 07 Unassigned VK_BACK 8 BACKSPACE key VK_TAB 9 TAB key DA 0B Unassigned VK_ CLEAR DC CLEAR key VK_RETURN 0D ENTER key DE OF Unassigned VK_SHIFT 10 SHIFT key VK_CONTROL l1 CONTROL key VK_MENU 12 ALT key VK_PAUSE 13 PAUSE key VK_CAPITAL 14 CAPS LOCK key 15 19 Reserved for Kanji 380 Windows Assembly Language amp Systems Programming VK_ESCAPE WK_SPACE VK_PRIOR VK_NEXT VK_END VK_HOME VK_LEFT VK_UP VK_RIGHT VK_DOWN VK_SELECT VK_PRINT VVK_EXECUTE VK_SNAPSHOT VVK_INSERT VK_DELETE VK_HELP VK_0to VK_9 VK Ato VK_Z VK NUMPADO to VK_NUMPAD9 VK_MULTIPLY VK_ADD VK_SEPARATER VK_SUBTRACT VK_DECIMAL VK_DIVIDE VK_F1 to VK_16 VK_NUMLOCK 1A 1B 1C 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2c 2D 2E 2F 30 39 3A 40 41 5A 5B 5F 160 69 6A 6B 6C 6D 6E 6F 70 7F 80 87 88 8F 90 Unassigned ESCAPE key Reserved for Kanji SPACEBAR PAGE UP key PAGE DOWN key END key HOME key LEFT ARROW key UP ARROW key RIGHT ARROW key DOWN ARROW key SELECT key OEM specific EXECUTE key PRINTSCREEN key INSERT key DELETE key HELP key O 9 same as ASCII Unassigned A Z same as ASCII Unassigned Numeric keypad Multiply key Add key Separater key Subtract key Decimal point key Divide key Function keys O 16 OEM specific Unassigned NUM LOCK key VK_OEM
372. n se pwindow still points to the parent window object so mov bx pwindow mov ax bx hwnd mov si hwndparent ax nending lea bx si szclassname lea ax si sztitlename call CREATEWINDOW PASCAL ds bx ds ax si createstylehi si createstylelo si x_coord si y coord si wwidth sil wheight si hwndparent si hmenu mainl hinstance 0 0 mov si hwnd ax save handle in window object ending ret Program Design 75 CONTROLmake ENDP Comparison You can treat the control object just as you would a window between object using all the same data and function members To make CONTROL and this statement almost completely true does actually require a little WINDOW classes OOP overhead Make file NOTE quirks H H HE HE HE HE claims to have improved compatibi this I haven t yet tried To run this file NMAKEWINASMOO MAK more refinement message wparam and lparam data members of the control object are not actually used so it would be wise to put in some testing to avoid them being accidentally accessed though this is unlikely Ditto for most of the functions The problem with inheritance is that I cant throw away the previous structures fields All I can do is redefine them Actually although there is redundancy here it is possible for a control to have its own callback which means that all of the fields would be of use One immediate refinement could be to o
373. n as a single client to DPMI Windows 95 32 bit applications have individual LDTs Real mode interrupts INT n INT 2 1h the main DOS service Windows functions Interrupt Vector Table IVT CPU Architecture 33 Interrupts Like everything else Protected mode interrupts are a whole new ball game First let s review the mechanism in Real mode The standard method of doing I O and file and memory management plus a heap of other operations was by the BIOS and DOS interrupt services These are accessed from an application program by means of the INT instruction with this syntax software interrupt where n is an integer whole number from zero to FF hex The usual procedure is that certain registers have to be loaded prior to the INT depending upon the particular service and many of the services have subfunctions usually selected by a value in the AH register The most important of these is INT 2lh h hexadecimal which is the main DOS service with dozens of subfunctions A comprehensive list is to be found in my previous book In this one you ll find extra INT services especially relevant to Windows It is not that we do away with INT services entirely with Windows it s just that many of the BIOS and DOS services are designed for DOS and the Real mode and are no longer appropriate We access the Windows services by CALL instructions not INTs and from the CPUs point of view there is a difference
374. ncorporated into the overall EXE tile and is executed if you try to run the program from the DOS command line It just displays a short message and quits I have put the DOS stub to very interesting use in Chapter 14 Make File Before we go ahead with the application itself lets consider the Make file This determines the assemble compile and link steps With reference to Figure 3 2 on page 74 the first step is to assemble SKELETON ASM to produce SKELETON OBJ any Include files are also assembled MASM and TASM have various directives to aid with creating Windows applications however by writing the program at the most fundamental level I have avoided these which means that just about any assembler should work You can see in the listing below how RC EXE is used to compile SKELETON RC and how to incorporate SKELETON RES into SKELETON EXE LINK converts the OBJ to EXE and LIBW LIB provides connection to the Windows functions LIBW LIB is not itself a library Note also that LINK refers to the DEF tile SKELETON MAR fn skeleton all fn exe fn obj fn asm masm fn fn res fn rc rc r fn re fn exe fn obj fn def fn res link f n NOD libw f n def rc fn res You create this on a text editor It requires a certain syntax and Make programs from different vendors have their own peculiarities The above will work with Microsofts NMAKE EXE and is for MASM vers
375. nd EXTRNs with PROTOs or delete the EXTRNs entirely However a major problem still exists the lack of a WINDOWS qualifer for PROC CMACROS This means that you cannot have a high level PROC declaration INC for the callback function and you have to resort to a macro or insert the prolog and epilog code manually The demo program uses CMACROSINC to achieve this Without the high level PROC you cant have the LOCAL directive for convenient creation of data on the stack CMACROSINC gets us around this problem Because a program isnt going to have too many callbacks its not a total disaster just a nuisance if you dont want to use CMACROSINC The manual approach is to insert the code as follows push ds Prolog code for callback function POP ax ae nop E inc bp E push bp mov bp sp E push ds mov ds ax dec bp Epilog code dec bp Eo mov sp bp pop ds Se POp bp a dec bp E ret 10 hwnd You can have local data on the stack but you will have to manipulate the stack directly To get at all of the data on the stack segment you could do something like this TEXTEQU lt WORD PTR bp 14 gt msgtype TEXTEQU lt WORD PTR bp 12 gt wparam TEXTEQU lt WORD PTR bp 10 gt 130 Windows Assembly Language amp Systems Programming lparam TEXTEQU lt DWORD PTR bp 6 gt dummy TEXTEQU lt WORD PTR bp 10 gt hdc TEXTEQU lt WORD PTR foe 12 gt s3 TEXTEQU lt bp 12 SIZE PAINTSTRUCT gt
376. nd does not tell the window callback to repaint the window Thus shifting a window under our special window can result in the underlying window picking up a ghost of our special window I have toyed with various ideas for telling the window to repaint its client area but did not put any code into this example for the sake of simplicity Anyway I see this more as a learning exercise and I dont think you should put these techniques into that professional office business suite youre working on On the other hand you never know when low level knowledge like this will come in handy 244 Windows Assembly Language amp Systems Programming I O Ports DOS assembly language programmers will be accustomed to using the IN and OUT instructions to talk with I O ports Of course with DOS it was very straightforward Execute OUT 28h AL to send a byte of data from the AL register to port address 28h and it happens immediately without question EFLAGS However with the CPU running in Protected mode there is some register extra rigmarole Since more than one task can be executing there has to be a mechanism to prevent contention First look at the flags register inside the CPU Figure 9 2 Figure 9 2 EFLAGS register FLAGS REGISTER VM RF NT IOPL OF DF IF TF SF ZF AF PF CF 14 13 2 11 10 reserved CF j carry flag FLAGS 16 bit PF parity flag register AF aux carry flag 86 286 eu aero ee
377. nd even only read from of data within data members of the current instance as pointed to by THIS an object Structure ofa function member textoutmain In OOP terminology this is the principle of encapsulation The data belonging to a particular object should only be accessed by functions belonging to that object and only if THIS is set to that object C does allow you to get around this but think of it as the ideal to be aimed for In assembly language you can break all the rules but you should try not to write 00 code that accesses data belonging to other objects If your function wants to access some data elsewhere the proper way to do it is to change THIS to that object and then call a function that is part of that object If no such function exists then you will have to write one Referring back to our earlier call to TEXTOUT with THIS set to window 1 the actual procedure called will be textoutmain which could have the following structure PROC PASCAL x y Now mov si now mov al si active lea bx window3 call bx TEXTOUT PASCAL x y bx ret textoutmain ENDP This skeleton shows how data member active is accessed Since the data ofany other object should notnormally be accessed directly Ihave put in some code to show how to change to another Pascal versus C stack handling Program Design 147 object and then call a function belonging to that object Upon return SI is still set t
378. ndler will crash Nor can a 32 bit application call a 16 bit function The next chapter backtracks somewhat and looks at the transition between DOS and Windows as Windows loads Understanding this can be very useful and will help with the above questions Integrating the code from previous Chapters 14 DOS Win Transitions Preamble This chapter further develops many of the concepts introduced in the previous chapters and also discusses some overall and related issues In this chapter I have built upon the issues of moving between various modes such as between VMs and between Real and Protected modes What happens to registers What about the stack What are the address mappings I have further developed the discussion of interrupt handling for Real and Protected modes I have also considered the issue of synchronizing between DOS and Windows For example how does a DOS driver know when Windows is loading How do you get a virtual device driver to cooperate with a DOS device driver Or to cooperate with a WinApp When writing the first edition of this book I paid a lot of attention to Standard mode In this edition I have considered it to be almost history so just about all of the code and description in this chapter is geared toward Enhanced mode i e requiring at least a 386 CPU 319 320 Windows Assembly Language amp Systems Programming API WinApps at ring 3 16 bit WinApps inferior to 32 bi
379. ndling for CALL and RET Involvement of the stack for CALL Code segment and RET These two must always occur in pairs InthecaseofaNEARCALL onlythe CPU s offset IP is altered a FAR CALL instruction has the will also alter CS value IPx as its The CALL pushes Pm onto the stack and loads its operand IPx into IP Note that the CALL operand Stack segment When IP has the new value IPx the subroutine ROUTINEX is executed and the RET instruction causes a return to the caller by popping Pm off the stack back into IP Figure 2 2 illustrates how the CALL and its companion RET use the stack The basic idea is that the value in the Instruction Pointer IP is always the next instruction to be executed so when CALL ROUTINEX is executing IP will have IPm in it Since the value in IP has to be changed to the subroutine IPx the return value has to be saved somewhere hence the stack is used to save IPm The RET instruction must always be placed at the end of a procedure as it pops the top off the stack back into IP If you have programmed in C or Pascal you know that you don t put a RET or anything special at the end of a procedure or function CALL and RET do go into the code though because the FAR and NEAR Code labels Basic Assembly Language 41 compiler translates the high level source code to machine instructions This topic does need some careful thought Any CALL RET or JMP instruction
380. ne distinct bus shown In a nutshell the bus carries the address and data and the bus that is directly connected to the CPU or processor is called the CPU system or processor bus The other possible buses perform the same basic task i e carry address and data but they are optimised for some specific purpose 179 180 Windows Assembly Language amp Systems Programming Address data and control buses Difference between memory and V0 access Machine cycle such as for connection to I O input output plug in adaptor cards Anybody who has been around PCs for awhile will have heard of the ZSA bus this is an example of such a special purpose bus The best starting point is to consider the structure of the bus that is directly connected to the CPU First we can analyse the CPU bus by breaking it into three logical groups of lines Really the bus is a big bunch of wires with certain wires carrying the address some carrying data and some performing control functions this is shown in Figure 1 5 on page 13 In fact each of these groups is sometimes referred to as a bus in its own right Intuitively you can imagine that if the CPU is to access memory it would have to send the correct address to memory on the address bus and the data transfer would take place over the data bus But what about I O If the CPU wants to send data to an output device for example a printer there is the same scenario of these
381. ne thing to bear in mind is that you are in a multitasking environment so feel free to run Windows programs alongside the DOS box You can have File Manager I mean Windows Explorer running for the purposes of testing the program You can use a Windows hosted text editor or a DOS based text editor Everybody has a favourite I use Microsofts Programmer s Workbench v4 01 which is DOS based There are a zillion editors on the Internet that can be downloaded Arguably the best for assembly language development is ASM_EDIT a complete IDE with extensive help files It is quite interesting to see color coded assembly code ASM_EDIT is shareware but the warning window comes up so frequently it is almost unusable that is if you have a low tolerance level The price in February 1997 was US 20 The main Internet page is http www skysurf de asmedit ae_whats htm Various people have experimented with stand alone Windows applications written entirely in assembly language Sven Schreiber has developed WALK32 a complete package for MASM even with its own linker It is public domain and can be found at the site http www thepoint net jkracht pdnasm htm 318 Windows Assembly Language amp Systems Programming SKELETON A 32 bit skeleton program written by Wayne Radburn for MASM ZIP a v6 11 uses the latest features of MASM much like the example skeleton for given inthis chapter If you have MASM v6 1x have a look at MASM6
382. nearly dont worry though as the hands on exercises begin soon If you feel the overwhelming desire to try the program why not flick ahead to the next chapter if you want to assemble the simplified skeleton Copy the appropriate tiles off the Companion Disk Then assuming that you have all the development tools installed follow the above instructions to assemble link and test your program Later on you can learn how it works internally Alternatively you may feel that you dont want to get bogged down in a skeleton that is very primitive and would prefer to jump directly into a skeleton that uses the higher level assembler features In that case study this chapter theoretically only and do your hands on work in Chapter 5 Or if you really insist on short circuiting my ladder of learning you can get hands on experience with the 32 bit application in Chapter 13 94 Windows Assembly Language amp Systems Programming Application Structure It doesnt do much more than put Hi there on the screen but wow so much red tape A far cry from the few lines a DOS program would need Try to understand as much as possible and identify the major structural elements Preliminary Code SKELETON ASM Windows assembly aenenaee program set 286 286 instruction WINDOWS The identifiers equates shown below would normally be in the INC WINDOWS INC Include file refer page 109 With this skeleton I have minimized the
383. ng of the currently running task GetEnvironmentStrings GETFBEES YSTEMBESOUBCES Only available in Windows 3 1 Returns the percentage of free system resource space GETINPUTSTATE Returns TRUE if there is mouse or keyboard input GETINSTANCEDATA Copies data from a previous instance of the application to the data area of the current instance GETKBCODEPAGE Determines which OEM ANSI code pages are loaded 210 Windows Assembly Language amp Systems Programming e GETKEYBOABDSTATE Copies an array that contains the state of keyboard keys e GETKEYNAMETEXT Retrieves a sting containing the name of a key from a list maintained by the keyboard driver e GETKEYSTATE Retrieves the state of a virtual key e GETNUMTASKS Returns the number of tasks currently executing in the system e GETSELECTOBBASE Not described in SDK 3 0 Gets the linear base address of the specified selector from the descriptor table e GETSELECTORLIMIT Not described in SDK 3 0 Gets the limit of the specified selector from the descriptor table e GETSYSTEMDEBUGSTATE Only available in Windows 3 1 Returns system status information to a debugger e GETWINDEBUGINFO Available in Windows 3 1 only Queries current system debugging information e GLOBALDOSALLOC Recommended by Microsoft instead of equivalent DPMI service Allocates a block below IM linear address space Returns both a selector and segment Complement is GLOBALDOSFREE e GLOBALFIX
384. ng start up that replaces the address in the the IVT with a new address that points to code in ROM on the video board Figure 7 6 shows the effect of an adaptor card During the power on sequence the BIOS startup code sets up the IVT at the beginning of RAM and puts ISR pointers into entries zero to 1Fh Entry 10h is the video handling ISR and this entry points to an ISR in the BIOS ROM Figure 7 6 BIOS extensions during power up MEMORY MAP Entry 10h in the IVT points to an ISR in the BIOS ROM however start up code in the video ROM changes the vector to point to a new ISR in the video ROM VIDEO ADAPTOR CARD on motherboard Connector for monitor 640K 0000 30000 0000 30000 Plugs irito PC expansion bus 40000 0000 IML A little bit later in the start up sequence the memory address range C0000h to C8000h is scanned in 2K increments looking for any code that may be present on plug in cards Usually an adaptor card has switches that set the address range of the 190 Windows Assembly Language amp Systems Programming BIOS amp DOS vectors in IVT Difference between BIOS and DOS services on board ROM to a vacant place in the PCs memory map Note though that Plug and Play is replacing switches with programmable configuration It is normally expected that a video adaptor will have video ROM in the C0000h to C8000h region in which case it executes When the s
385. ngers Road 25 First Lok Yang Road Maidenhead Singapore 2262 Berkshire SL6 2QL Tel 65 268 2666 United Kingdom Fax 65 268 7023 Tel 0800 810800 or 01628 502500 Fax 01628 770224 e mail queries mcgraw hill co uk Latin America Editorial amp Marketing Office ID International R amp D Books 126 Old Ridgefield Road 1601 West 23rd Street Suite 200 Wilton CT 06897 USA Lawrence KS 66046 Tel 203 834 2272 Tel 913 841 1631 Fax 203 762 9725 Fax 913 841 2624 e mail orders mfi com Web http www rdbooks com Ch l Contents Page Preface xi CPU Architecture I Preamble sun Gneis Rasa ede e e tied oS OEE eee BRA KOE Power up the PC csccceecc cnet ete neeneeteneneeeecenes 2 THE System Piles i054 aiken y Oe cee EAE 3 Number Systems s sesseoessseeposenesesssoooresesesere 6 Registers and Memory lt s a2ids2 es tide inadiaceindetanbiass 9 Memory Map of the PC cece eee eee 12 The CPU amp Support Chips eeeeeee eee cece ee enees 12 Conventional and Extended Memory e eseeeeeeess 14 Sep ment aea N A er ede teee eects me wees 14 Real Mode jacneeidenv edt san o A E yee EEA 17 DOS Real Mode Programming eeee eee ees 18 DOS Protected Mode Programming seeeeeeeee 18 Coding Restraints aicciusacssisas vee seen ehoesete sine 20 Inside the 286 386 486 etc 6 cece cece cece eee ences 21 CPU RCSIS G1S scvieewun iene ccieee ee mime A EAA 22 INSUUCHIONS sesei eup in
386. nisms by which this is done are called the addressing modes The best way to show this is by example VAL1 DW 0 MOV AX BX register addressing mode MOV AX 567 AAmmediate addressing mode MOV AX 567 direct addressing mode Basic Assembly Language 45 MOV AX VAL1 jdirect addressing mode Mov instruction Register amp immediate addressing Direct addressing syntax Indirect and indexed addressing mov ax mov ax mov ax Restrictions on indexed addressing The humble MOVe instruction is the equivalent of the LoaD Acc and STore Acc instructions of the 6800 CPU for those who have had exposure to that beastie It simply moves a value from one place to another in this case copying the value of BX to AX Because only registers are involved in the first instruction of the above example this is called register addressing The same MOV instruction appears again on the second line but note that a value is specified this time This value is NOT an address it is an immediate value that is loaded into AX This is called immediate mode addressing Now this is different The square brackets of the third instruction signify the contents of and it is the contents of address 567 that is loaded into AX there is a qualification to the above comment as the example loads the AX register which is 16 bits from a memory location which is 8 bits Note too that with an assembler not primitive DEBUG though
387. nnector was retained but a second connector that the 16 bit cards used was placed end on to it Although 8 bit cards will work ok in a 16 bit ISA system they will not run quite so fast as 16 bit cards This is something to be aware of when shopping around a display adaptor card for example could be 8 or 16 bits There are other books with a stronger hardware focus that will give you further details such as the functions of the pins on an ISA bus connector and timing diagrams One such book is Interfacing to the IBM Personal Computer by Lewis Eggebrecht Sams USA 1990 A plug in card gets an opportunity to execute configuration code stored on ROM on the card during the power on sequence One of the typical things that this code does is hook interrupt vectors For example a video card may hook the BIOS INT 1 Oh interrupt In such a case the address in the IVT will point to the new code that replaces it This redirection is done by DOS itself by device drivers and TSRs and by plug in expansion cards that may have their own ROM with startup code and new BIOS routines PC Hardware 189 Video is a very good example of this Most PCs have plug in video adaptor cards that are the interface between motherboard and monitor This card plugs into an expansion bus connector The original video services provided by the BIOS ROM are at entry 10h in the IVT however it is normal for the video card to execute some code duri
388. nstraints such as requiring handles to access all screen I O and of course using selectors instead of segments for data and code manipulation Perhaps the newness of this is making you feel uneasy However the hands on examples a bit later should alleviate that Building a Windows Application Library Functions The Windows routines operate like C functions though stack handling follows the Pascal convention The library of functions can be split into three types e KERNEL e GDI e USER Whenever you want to do any kind of I O operation including everything else involving the operating system such as various memory management operations you can call these functions They are just like the BIOS and DOS INT services except they are called by the assembly language CALL instruction Locations of So where are these functions actually located If you look in the the DLLs C WINDOWS SYSTEM subdirectory assuming that you installed Windows in the default directory you will see the three files KRNL386 EXE GDILEXE and USER EXE You will also see KRNL286 EXE which is the version of KERNEL for Windows 3 x running in Standard mode Windows 95 only has KRNL386 EXE not KRNL286 EXE These files provide the API for 16 bit WinApps For 32 bit WinApps Windows 95 also has KERNEL32 DLL GDI32 DLL and USER32 DLL Actually Windows 3 x follows the Pascal calling convention and Windows 95 and NT follow a mix of Pascal and C conven
389. nt Make has been presented in this chapter in a simple uncluttered form as has the rest of the code The INC tile can be massaged in various ways to do more For example make can be made to handle normal child windows with only minor modifications Thus the same WINDOW class could be used for parent and child windows The alternative would be to create another class called say CHILD just like I did for CONTROL The product is evolving all the time and you may find some interesting new stuff on the Companion Disk or my Web site Postamble You can have a lot of fun playing with these tools You may think of improvements let me know PC Hardware Preamble This could be an enormous chapter I m an electronic engineer so the hardware is my forte and I could keep writing for some time However the publisher only agreed to a book of around 400 pages and I m already pushing it Very few assembly language books delve deeply into the hardware and certainly no Windows books do Well many Windows programming books do cover more or less the CPU architecture and memory management as I have done in Chapter 1 For systems programming it is very helpful if you understand something about the hardware beyond the CPU i e the other chips on the motherboard and plug in cards how they work together and how to utilise them CPU Bus Look at any block diagram of a computer system and you are likely to see more than o
390. nt TASM User Ss Despite a wonderful new assembler Borlands manual has only manual about two and a half pages devoted to Windows programming and limitations amp only two demo programs on disk The OOP neophyte will find the TABLE TASM manual to be quite daunting with all of the 00 description terminology The manual supplied with TASM version 5 has even less documentation This book addresses all of these problems Not only do I demystify OOP but I show how to write windows programs effortlessly The Borland manual describes the use of TABLE to define function members methods for an object with the data members defined separately There are certain reasons for this but I wanted a system that is conceptually simple Notice the VIRTUAL qualifier in front of every field declaration Dont worry about this just pretend it isnt there Readers with some knowledge of OOP will know that VIRTUAL is a qualifier used with functions but Ive also put it in front of data members because I have used TABLE in a way that Borland never intended or thought of 160 Windows Assembly Language amp Systems Programming Analysis of the table TABLE overrides DATA Look at the first field def inewndclass is a NEAR pointer to a procedure WINDOWdefinewndclass What this actually means is that when an instance of the structure is created the field will be as per Figure 6 1 Window equates to the offset in the segme
391. nt at which the structure instance starts Detinewndclass equates to 0 being the first field while create equates to 2 This is exactly as in any normal structure The contents of the fields are addresses of the procedures in this case they are default procedures defined within WINASMOO INC Figure 6 1 definewndclass pointer create paint mi OU oat These addresses are forward references which is why STRUC wont accept them and why I have used TABLE With STRUC you have to put them in when creating the instance which I used to do by means of a macro Further down in the WINDOW structure youll see plain old data which should be easy enough to understand Apart from being able to declare forward references the beauty of the TABLE directive and TASM s new extended STRUC is the declaration of overrides when creating instances A TABLE or STRUC declaration is only for the assembler use and is not actually assembled It is the instances that get assembled A static instance is one that you declare in the data segment You could declare automatic instances on the stack or dynamic instances on the heap Dynamic instances involve an extra level of complexity so let me shelve that one for now The skeleton program on page 154 declared a static instance as follows windowl WINDOW szclassname WINASMOO sztitlename Main Window paint wlpaint create wlcreate command wlcommand Program Design 6 Overridin
392. nt register CS and the Instruction Pointer IP at power on or after resetting the CPU combines these two in a certain way to produce an address on the address bus Note that this address is 20 bits in size because the 8088 and 8086 have a 20 bit physical address bus The 286 386 486 and Pentium have larger physical address buses but only use 20 bits in startup Real mode That is even the powerful Pentium starts up behaving just like its ancestor this is a very important point Figure 1 3 also shows the major components of a PC note that they are all connected by something called the bus To access memory contents addresses must be sent out from the CPU microprocessor and the very first address is a combination of CS and IP 10 Windows Assembly Language amp Systems Programming Figure 1 3 What is a register WHAT IS A REGISTER Just as the PC has memory chips called RAM changeable contents lost when turned off or ROM permanent program storage which sit somewhere in the memory map so too the CPU chip has internal RAM memory called registers Registers are 8 16 or 32 bit memory locations but are not addressed like external memory Instead each of these registers has an explicit unique name that can be used in the machine language instructions The 8086 has these registers AX BX CX DX SI DI SP BP CS DS SS ES Some are general purpose and some have special purposes this is something that is l
393. ntain the executables in which case you can run them immediately You will need to place WINAPP EXE into C i e the root directory of the C drive WDEMOD EXE can be anywhere From the DOS prompt not a DOS box inside Windows go to the directory that has VDEMOD EXE and run it by typing VDEMOD Then type WIN to load Windows 340 Windows Assembly Language amp Systems Programming Assembling and linking nannan vvvyv VxD Lite The loudspeaker should start a continuous tone letting you know that the VxD has loaded Then the WinApp will load When I first did this on Windows 3 1 up came the Program manager but not my WinApp where was it This is interesting WINAPP EXE loads before Program Manager so it is hidden underneath This is not a problem with Windows 95 and you should see the WinApp appear on the desktop Mind you its a stupid WinApp as youll see To assemble and link everything type this nmake A winapp mak copy winapp exe c nmake A tsr2win mak nmake A vdemod mak You must assemble and link TSR2WIN before VDEMOD To assemble and link VDEMOD the VxD you need special tools and Include files from the Device Development Kit DDK which normally means that you have to join the MSDN which means considerable expenditure There is however VxD Lite which Microsoft did provide free a couple of years ago It is now withdrawn and I was unable to obtain permission to place it on the Com
394. nterrupts You will notice that my example code earlier in this chapter dealt only with software interrupts Hardware interrupts can work but there are some complications The problems are associated with how interrupts are mapped and the difference in treatment of interrupts in Protected and Real modes The issue is very complicated and it behooves us to start with the handling of hardware interrupts from the point of view of the XT that is with an 8088 or 8086 CPU XT Hardware Interrupts The PC model XTs are based upon the 8086 CPU and have a hardware interrupt controller chip that allows eight devices to interrupt the CPU That is the chip has eight inputs labelled IRQO to IRQ7 and one output labelled IRQ Interrupt ReQuest that feeds into the maskable interrupt pin of the CPU A flag named IF Interrupt Flag enables this IRQ input with the STI instruction or disables it with the CLI instruction see page 33 The interrupt controller chip can be and is programmed to map IRQO to IRQ7 to any group of eight entries in the IVT or IDT Real Time Events 257 look ahead to page 268 for the relationship between the IVT and IDT see page 185 for an introduction to the interrupt controller chip The XT maps IRQO through 7 to entries 8 to OFh in the IVT Thus if you were to access these by software interrupt you would execute INT 8 to INT OFh AT Hardware Interrupts The IBM model AT based upon the 80286 CPU intr
395. ntroduced back on page 41 Code Labels In the case of a code label the syntax is that it should start in column 1 and be suffixed with a colon as in this example jmp placel jumping to somewhere in the program es gt a code label Code labels equate to their address NEAR and FAR Procedures call routinel ret routinel PROC and ENDP Basic Assembly Language 57 When the assembler assembles the source code it replaces jmp place with the operation code for a JMP jump instruction followed by the address place as the operand to the instruction Thus the assembler equates place to the offset it is marking This is a vital point the assembler simply replaces all occurrences of placel in the code with the offset address it equates to Normally we would be jumping within the current code segment so placel equates to an offset from the start of the segment that is the IP value of that point in the code A jump within the segment is called a NEAR jump Note that it is also possible to jump between segments which would be a FAR jump and I have elaborated on this later in the book Another very important point is that any transfer of control instruction such as a JMP or CALL can have various addressing modes These modes are encoded by the assembler as part of the instruction operation code The above JMP example would be what we call immediate addressing as the operand i
396. number yes Windows 95 still has DOS so there is still a version number MSDOS SYS contains all the DOS service routines The MSDOS SYS routines are more sophisticated and we can think of them as the next level up from the BIOS routines That is the file contains code However with Windows 95 the functionality of MSDOS SYS is changed It is merely a small text file You might like to investigate this for yourself if you are currently using Windows 95 Make sure that Windows Explorer is setup to show all filename extensions and hidden files Then view the C drive root directory Double click on MSDOS SYS and select NOTEPAD EXE to view the file Be careful about making changes but do note the following very interesting lines 4 Windows Assembly Language amp Systems Programming Options BootGUI 1 BIOS amp DOS service routines COMMAND COM Internal amp external DOS commands If you change the entry to BootGUI 0 the next time you boot the PC it will load COMMAND COM not WIN COM so you will be in plain old DOS Of course the DOS service routines are elsewhere in the case of Windows 95 not in MSDOS SYS but the boot process still knows where they are and loads what is required Note that the BIOS and DOS service routines are there for us to use when writing programs There is a simple method for us to call any one of these subroutines from our program Basically these routines enable us to int
397. number of files involved ID1 APPLICATION EQU 32512 default icon type IDC ARROW EQU 32512 default cursor type OEM FIXED_FONT EQU 10 font type COLOR BACKGROUND EQU 1 background color WM CREATE EQU 1 Windows message WM DESTROY EQU 2 WM PAINT EQU 15 WM COMMAND EQU 273 WM LBUTTONDOWN EQU 513 WM CHAR EQU 258 i IDM QUIT EQU 100 menu identifiers from IDM ABOUT EQU 101 is RC file MB OK EQU O messagebox identifier Program listing The Windows startup code would normally be in a continues until page separate OBJ module supplied by the compiler vendor 107 however in this fundamental skeleton I have put the startup code into this module This code is taken from APPENTRY ASM which is the source file for Generic program for APPENTRY OBJ supplied by Microsoft These are a any assembler couple of equates used by the startup code This is the equates for the startup code STACKSLOP EQU 256 amount of stack slop space required maxRsrvPtrs EQU 5 number of Windows reserved pointers The Bare Bones 95 Below are the Windows functions that the program calls In assembly language we must declare all external functions which is not an essential requirement in C High level MASM version 6 00 is an interesting exception to this as its CALL INVOKE high level CALL is C like and doesnt need an explicit EXTRN declaration MASM v6 00 is also C like in that it accepts the C spelling of EXTERN
398. o even more Memory Management The 286 has just one Protected mode also inherited by the 386 and we will look at that first It employs mapping of the segments to memory via Local Descriptor Tables LDTs and a Global Descriptor Table GDT Note that the 386 can work exactly like the 286 but also has other modes an extension to the descriptor tables with page tables and a system with page tables only known as virtual 86 mode Segmentation Only There is only one GDT but the operating system maintains an LDT for each program currently running Windows 3 x and 95 are special cases see footnote on page 32 Think about the LDT it contains the actual segment addresses while the segment registers inside the CPU we will now call them selectors are just indexes into the LDT When a task switch occurs the CPU has a simple mechanism for changing to the next LDT but the selectors don t necessarily have to change since they only index into the table 26 Windows Assembly Language amp Systems Programming Purpose of the GDT How many LDTs Descriptors Fundamental reasons for having the LDT are the increased addressing plus protection Ok here is a picture take a look at Figure 1 12 The figure gives a fairly good idea of the relative roles of GDT and LDT When the operating system first creates the GDT it uses special instructions to put the base starting address of the GDT into the 32 bit GDT register Thus the
399. o large Int 31h Function 0303h Allocate Real Mode Callback Address Returns a unique Real mode segment offset known as a Real mode callback that will transfer control from Real mode to a Protected mode procedure Callback addresses obtained with this function can be passed by a Protected mode program to a Real mode application interrunt handler device driver or TSR so that the Real mode lt program can call procedures within the Protected mode program or notify the Protected mode program of an event Call with AX 0303h DS E SI selector offset of Protected mode procedure to call ES E DI selector offset of 32h byte buffer for Real mode register data structure to be used when calling callback routine Returns if function successful CF clear CX DX segment offset of real mode callback if function unsuccessful CF set AX error code 8015h callback unavailable Int 31h Function 0304h Free Real Mode Callback Address Releases a Real mode callback address that was previously allocated with the Allocate Real Mode Callback Address function Int 3 lh Function 0303h Call with AX 0304h CX DX Real mode callback address to be freed Returns if function successful CF clear if function unsuccessful CF set AX error code 8024h invalid callback address Int 31h Function 0305h Get State Save Restore Addresses Returns the addresses of two procedures used to save and restore
400. o do it There are various reasons why you may want to do everything from DOS and load Windows to test the program or have a DOS box open and use lt ctrl esc gt to flip between it and Windows Or you may be working within an integrated environment which may have something called a projectfile rather than a Make file Many integrated environments can generate a Make tile from a project file and can also execute a Make file from within the environment I have never been entirely satisfied with integrated environments and prefer to be outside one using the traditional Make file from the command line but I dont want to prejudice you If your product has an integrated environment give it a go One problem you may have is getting it to handle stand alone assembly programs Prog rammer3 However I have rather grudgingly come to like Microsofts Workbench When can I get started Programmers Workbench PWB If you install PWB you can open almost any of the Make files supplied on the Companion Disk and thus you will have opened a project You will however have to click the non PWB Makefile button Then you can select Rebuild All from the Run menu and see the result in a Build window PWB can be started from within Windows and after running the Make tile you can use lt alt tab gt to flip over to Windows and try the program This is of course just theory if you are reading through the book li
401. o this function current object Examine this code and you may be surprised What function is actually being called by the CALL and why is it ok That for you to think about Interfacing with C Although I have standardized on the Pascal calling convention for most of this book for compatibility with Windows functions standard C handles the stack somewhat differently It is not something that will cause much trouble since you can take care of everything by use of the high level CALL instruction and PROC directive However in the case of passing THIS to the called routine you will need to know whether it is pushed on first or last With Pascal the high level CALL pushes the parameters on in the order in which they are listed that is the leftmost one first The high level procedure that is being called will automatically remove the parameters from the stack before returning to the calling level With C the high level CALL pushes the parameters onto the stack in the reverse order so the leftmost one gets pushed on last The called procedure does not clean up the stack before returning and the parameters must be removed from the stack after return to the calling level Code for the latter operation is generated automatically by the high level CALL by the C qualifier C also pushes THIS onto the stack last in the case of calls to function members Thus your PROC declaration will need to show THIS as the leftmost paramete
402. oads WinApp VxD 332 TSR_INFO_STRUC 333 Turbo Debugger 317 TWORD 80 bit 63 Type mismatch 63 Type override 63 Types of data 63 82 U UNHOOKWINDOWSHOOK 212 Unsigned number compare 51 Unsigned numbers 7 UPDATEWINDOW 101 157 USER EXE 72 23 1 Video mode changing of 232 Video RAM writing pixels to 239 VGA 242 Virtual machine VM 30 271 Virtual Method Table VMT 177 VIRTUAL aualifier 158 Virtual to physical address mapping 271 Virtual Real mode 271 Virtual 86 V86 mode 29 271 Visual programming 358 VMM amp VxD services calling 302 VMMCALL 354 VMs mapping across 342 VxD anatomy of 350 VxD assembiing amp linkin 350 VxD automatic loading o 330 VxD device descriptor block 352 VxD DOS stub 331 W WAITEVENTQ 98 WIN32_ STARTUP_INFO_STRUC 333 WIN COM 2 WINDOWS qualifier 118 126 WINDOWS H 110 128 WINDOWS INC 94 112 WINEXEC 212 WINMAIN 77 98 WINSTUB EXE 91 WM_CHAR message 105 WM_COMMAND message 90 106 WM_CREATE message 104 WM_DESTROY message 104 260 WM_LBUTTONDOWN message 104 WM_PAINT message 105 WM_USER message 261 WNDCLASS structure 121 WndProc 79 WORD 16 bit 58 63 WORD PTR 63 WOW functions 221 wParam 90 X XOR instruction 55 Y YIELDQ 212 PRODUCT amp PUBLICATION REFERENCES Archive Library CD ROM 197 339 ASM_EDIT IDE 317 Assembly Language Lives 367 DDK 197 203 Dirty Little Secrets about Windows 95 235 DJGPP 197 DMA Revealed 264 DOS 5 A Developer s Guide 291 DPMI I 0 Specific
403. ode cannot be changed Even though you can keep data in the code segment and I have done so in the skeleton program you cannot change it Windows sets the attribute of code segments such that they cannot be written to and your program will crash if you try Most interestingly though there is a way around this because Windows has a function that gives you a DS selector for a code segment see Chapters 10 11 and 12 Note that my OOP code is designed for the SMALL model The major limiting factor is the pervasive use of NEAR pointers It would probably be easier to design a completely different Include file for other memory models It should be easy to upgrade to 32 bit code though TASM v3 0 encourages the classical implementation of objects in which the pointers to procedures Virtual Method Table VMT are 178 Windows Assembly Language amp Systems Programming Improving Make not stored physically with the data of each object instance but somewhere else which is why they invented the TABLE that I have misused There are arguments for and against this Any one class can have one VMT and instances could all access a single instance of the VMT This would be efficient in terms of memory but would not allow individual overrides by each object instance As mentioned earlier I decided on an approach that allows easy conversion to non OOP assemblers is conceptually simple and offers some flexibility advantages that the VMT does
404. oduced more hardware interrupts by cascading a second interrupt controller chip as shown in Figure 10 1 Figure 10 1 AT hardware interrupts IVT Divide by 0 Single step NMI REAL MODE HARDWARE INTERRUPTS Breakpoint Overflow Print screen reserved reserved 55mSec_ timer Keyboard Cascade for IRQ8 0F Usually COM2 Usually COMI Usually LPT2 Diskette Usually LPT1 Video I O Equipment check n 0 1 2 3 4 5 6 7 19 GA ZB C D p p S m f 70 Realtime clock 72 general 73 general Second interrupt 74 general controller chip 75 Coprocessor added to the AT B 76 Hard drive 77 general 258 Windows Assembly Language amp Systems Programming Exception handling conflict Windows remapping of vectors At power on the interrupt controller chips are programmed to map to certain entries in the IVT When an interrupt arrives IRQ is forwarded to the CPU and the CPU then interrogates the controller chip which passes the interrupt number n to the CPU over the data bus The CPU then looks up that entry in the IVT and goes to the interrupt service routine When the CPU is operating in Real mode INT 0 is what is called a processor exception that is an interrupt generated by the CPU itself not by the program or by external hardware Ditto for INT 1 I have shown INT 6 and 7 as reserved which is the case for the XT However on the AT the 286 CPU uses these for invalid op code and
405. oexec bat file Note that the Include files are in the path shown below change if necessary masmS5 exe 1ink386 exe addhdr exe imapsym32 exe must all be in the search path or put in current directory to run NMAKE A VDEMOD MAK there is also a BUILDALL MAK I have put a path of c vxd for the INC files but replace as necessary comment this definition out with a if building a non debugging version Debug DDEBUG 352 Windows Assembly Language amp Systems Programming all VDEMOD exe asm obj masm5 p w2 Mx Debug Ic vxd asm lst masm5 1 p w2 Mx Debug Ic vxd VDEMOD obj VDEMOD asm c vxd debug inc c vxd vmm inc OBJS VDEMOD obj VDEMOD exe VDEMOD def OBJS link386 VDEMOD 1nk addhdr VDEMOD exe mapsym32 VDEMOD VxD tools Ok now for the DEF file LIBRARY VDEMOD DESCRIPTION Barry Kauler VxD for Microsoft Windows STUB TSR2WIN EXE EXETYPE DEV386 SEGMENTS _LTEXT PRELOAD NONDISCARDABLE _LDATA PRELOAD NONDISCARDABLE _ITEXT CLASS ICODE DISCARDABLE IDATA CLASS ICODE DISCARDABLE TEXT CLASS PCODE NONDISCARDABLE _DATA CLASS PCODE NONDISCARDABLE EXPORTS VDEMOD_DDB 1 The above two files are the standard red tape adaptable to other VxDs However one special difference is the TSR2WIN EXE stub For other VxDs you can replace this with a dummy do nothing stub and also you may prefer to generate a VxD with a 386 extension Th
406. of DPMI that enables applications to call terminate and stay resident TSR programs and device drivers running in Real or virtual 86 mode This is a direct quote from some loose leaf pages sold by Microsoft under the title Windows Developers Notes part number 050 030 313 It is extra material not found in the SDK and has a couple of pages on DOS and DPMI hardly anything though as it appears that Microsoft has the attitude that the less we know about how Windows works under the hood the better Despite documentation to the contrary see quote below Windows 3 0 3 1 and 95 only support DPMI version 0 9 The Windows Developers Notes have the following warning stated 1 Much of the material from the Developers Notes has found its way into the latest SDK for Windows version 3 1 This consists of about 12 books DOS and DPMI notes are to be found in Microsoft Windows Programmers Reference Volume I Overview the first of four volumes This is now on CD ROM supplied with the SDK though in many cases Microsoft will sell printed versions BIOS DOS Windows Services 199 If you think that the above two quotations are contradictory join the club What it to be 0 9 or 1 0 I received a clarification from Microsoft that Windows 3 0 and 3 1 and now 95 only support DPMI 0 9 Their reply to me also had another interesting comment a Standard mode understands how to allocate memory from a DPMI provider
407. of Make a note of this All values are stored in memory with the storage of lowest byte at the lowest address and the highest byte at the data in highest address That is why I added 2 to the second MOV memory instruction It may be that in my program I want to see what is contained in ptr4 Any data label defined as having a 32 bit value has a problem with the 8088 8086 and 80286 because there are no 32 bit registers So if I wanted to get that value into a register I would actually have to use two registers That is why I am forced to use those two MOV instructions with worn PTR overrides even for the 386 for compatibility with the other CPUs In Chapter 4 you will see plenty of examples of this If we write code for the 386 and upwards exclusively then a simple mov EAX ptr4 would do the trick Storing 32 bit There is another way to approach the problem of handling 32 bit data under data split it in half two 16 bit If you have to store a FAR address say in a pointer you can split label it into two data labels DATA ptroffset DW 789h far pointer stored in ptrsegment DW 1234h two pieces CODE mov BX ptroffset mov ES ptrsegment This may not be practical for data values but for FAR addresses in the form of 16 bit segment offset it works fine It means that source and destination types will match so no override is required More on Another little note just as with the x86 family we always store o
408. ogramming CMACROS Include file TASM s WINDOWS qualifier Windows aware but its C like features did in time endear themselves to me Note however that Microsoft did make MASM much more Windows aware with the release of version 6 1 MASM v6 00 is a stand alone product and as such cannot be used for Windows development again corrected by 6 1 The user s manual has barely a line or two on Windows the documentation for 6 1 is also a disappointment in this regard The product 6 0 is for DOS and OS 2 development and those interested in Windows programming are referred to the SDK Obviously if you have v6 0 upgrade it Note however that you still need the SDK with MASM v6 1 To quote from the Microsoft Programmers Guide supplied with MASM v6 1 page 258 MASM 6 1 does not provide all the tools required to create a standalone program for Windows To create such a program called an application you must use tools in the Windows SDK The required tools such as resource compiler and libraries arent there so you need the SDK or one of Microsofts recent Windows aware higher level languages The 6 x package does have CMACROS INC which is required for Windows development but it is not described in the manual Once again the SDK is the place to look WINDOWS Qualifier TASM v3 x TASM3 has extended the syntax of the language in a very systematic manner notably with the extended PROC and CALL and most espe
409. omodule userexists Gall FAR PTR GETPROCADDRESS PASCAL si 0 275 275 ordinal value of REPAINTSCREEN in mov WORD PTR lprepaintscreen ax USER EXE mov WORD PTR lprepaintscreen 2 dx Returns far addr DX AX mov ax 1686h test if dpmi running int 2Fh or ax ax 47 yesitis jmp nodpmi yesitis mov dapmiflag 1l set flag dpmi ok mov ax 0400h get dpmi version int 31h mov dpmiversion ax mov al bl and al 01 bit 0 1 if 386 domi mov mode386flag al mov al bl shr al i and al 01 bit 1 1 if not virtual86 int handling mov realmodeintsflag al shr bl 2 and bl 01 bit 2 1 if virtual mem supported mov virtualmemflag bl mov cputype cl cl 2 3 4 if 286 386 or 486 mov ax 0002 mov bx 0B000h Asegment addr of video RAM it SIR Note that although DEATH is mov BOOOselector ax undocumented I figured out mov ax 2 how to use it Pae call GETDC PASCAL hwnd mov ax 4001h mov hdc ax int 2Fh call DEATH PASCAL hdc pees Windows display driver is oy oan now turned off and sern in in JIL text mode mov winvideomode al Note that DEATH leaves the mov ax 0007h mode 7 CPU in Protected mode 234 Windows Assembly Language amp Systems Programming int 10h mov ax BOOOselector mov eS ax mov bx 0O mm mov cx OFFFFh mmm nop loop mmm delay mov BYTE PTR es bx X mov BYTE PTR es bx 1 10001111b attribute inc bx inc bx cmp bx 1998 put 1000 X s on screen jbe mm Paea Undocumented RESURRE
410. omplete numbers They relate back to boolean algebra and as with the arithmetic instructions I assume a certain background knowledge You should have a basic understanding of the boolean AND OR EXCLUSIVE OR and NOT functions AND performs a logical AND on corresponding bits in two operands leaving the results in one operand mov al 01001000b and al 00001000b answer al 00001000b OR TEST is just like AND but only does the operation hypothetically and doesn t change the operands this is very similar in concept to the relationship between SUB and CMP OR performs a logical OR operation on two operands mov al 01001000b Basic Assembly Language 5 5 OK al 00001000b result al 01001000b XOR XOR performs a logical EXCLUSIVE OR on two operands mov al 01001000b xor al1 00001000b result al 01000000b NOT NOT complements all bits in an operand this is not a 2 s complement conversion see NEG mov al 01001000b not al result al 10110111b SHL SHR SHL SHift Left and SHR SHift Right do what they suggest but it is clearer if their operation is viewed diagrammatically Figure 2 1 Figure 2 7 Shift instructions Examples of shift and rotate instructions SHR AL 1 SAR AL 1 ROR AL 1 RCR AL 1 The example of SHR moves all bits in AL one place to the right and a O into the most significant bit MSB Note that the least significant bit LSB goes into the carry flag CF This instru
411. on 2 x returns Olh or OFFh Windows version 3 x returns the major version number in the AL register and the minor version number in the AH register Interrupt 2Fh Function 160th Get Enhanced Mode Windows Entry Point Returns the address of the 386 Enhanced mode Windows entry point procedure Applications can call this procedure to direct Windows 386 version 2 x to carry out specific actions This function applies to Windows 386 version 2 x only It is provided under Windows version 3 x for compatibility reasons Call with Ax Return value The return value contains the Windows entry point address in the ES DI registers Comments Although the Windows entry point address is the same for every virtual machine an application can call this function any number of times To direct Windows to carry out a specific action the application sets the AX register to 0000h This function retrieves the current VM identifier and copies the identifier to the BX register Additionally the application must place a return address in the ES DI register pair and use the jmp instruction to transfer control to the Windows entry point 1602h INT 2F Extensions 403 FORMAT Heading Description Call with Returns Comments Interrupt 2Fh Function 1605h Windows Initialization Notification Notifies MS DOS device drivers and TSRs that standard or 386 Enhanced mode Windows is starting Windows calls this function as it starts allowin
412. on to run you can call PEEKMESSAGE with the no yield option Windows undocumented functions can be a bonanza if we can figure out what they do DEATH Q RESURRECTION O DISABLEOEMLAYER and ENABLEOEMLAYER are extremely interesting The latter two go the whole way turning off Windows screen mouse and keyboard and restoring all normal DOS If O with the vital exception that we are still in Protected mode Writing pixels to the video RAM Overwriting the screen using BIOS and DOS Services a renegade window Direct Hardware Access 239 Experimenting One thing that you might like to do as an exercise is modify my code so that the mode is not changed Leave it as it was and change the segment address from B000h to A000h then you will have a selector to the graphics video buffer The EGA and VGA physical video buffers are at segment address AOOOh If the program sends ASCII X s to the screen you wont see X s because the screen is in graphics mode ASCII codes are only appropriate when the screen is in text mode In graphics mode you write pixels to the buffer and to know how to do that you need a good EGA VGA programming book In this simple example the X s will produce an interesting pattern on the screen You might like to experiment with commenting out the INT 3 1h 4002h and the REPAINTSCREEN A Direct Video Window Program I introduced the idea of overwriting the existing Windows screen back on page
413. one if you are writing the entire program in assembly language In this book we stick entirely with assembly Notice also the H and or INC Include tiles Strictly speaking these are optional which is why I didn t list them above The introductory program in this chapter only requires the ASM DEF RC and MAK files but in later chapters I have shown the use of WINDOWS INC H files are used with C programs and INC with assembly programs Borland and Microsoft supply utilities to translate H files to INC Functionally both types are the same just with different syntax to suit the C compiler or the assembler Include tiles contain equates and definitions that make the program more convenient to write 74 Windows Assembly Language amp Systems Programming Figure 3 2 Steps to generate an executable file C H INC ASM C Source file Include file s Assembly language C Compiler DEF Module Definition file Dynamic link library DLL Resource compiler source files Windows amp C libraries DEF Module Resource Definition file compiler RC Resource script compiler files EXE Note that linkers for 32 bit Windows 95 perform the function of the final resource compiler step The Link Step Notice how overloaded the LINK program is The job of a linker is to combine the various program modules to produce the final EXE but in this case there are extra complications The DEF Module Defini
414. ontents of the ES BX register pair to the Next_Dev Ptr member It is assumed that any other device driver or TSR in the Interrupt 2Fh chain will have set the ES BX register pair to the address of its own startup structure prior to returning Any device driver or TSR can use a Windows virtual device to help support its operation in the 386 Enhanced mode Windows environment To specify a virtual device the device driver or TSR sets the SIS Virt Dev File Ptr member to the address of the virtual device s filename The device file is assumed to be in the Windows SYSTEM directory The device driver or TSR can also set the SIS_Reference_Data member to specify additional data to be passed to the virtual device when loaded Any device driver or TSR can reserve instance data for itself Instance data is one or more blocks of memory used by the device or TSR and managed by Windows For device drivers or TSRs loaded before 386 Enhanced mode Windows starts reserving instance data allows the device driver or TSR to keep separate data for each virtual machine Whenever Windows switches virtual machines it saves the previous VM s instance data and loads the current VM s instance data If a device driver or TSR does not een instance data the same data is used for all virtual machines A device driver or TSR reserves instance data by appending an array of Instance_Item_Struc structures to the Win386 Startup Info Struc structure The last structu
415. ory Block Size and Base 050Bh Get Memory Information 0800h Physical Address Mapping 0801h Free Physical Address Mapping 0D00h Allocate Shared Memory ODO1h Free Shared Memory 0D02h Serialize on Shared Memory 0D03h Free Serialization on Shared Memory DOS MEMORY MANAGEMENT SERVICES 0100h Allocate DOS Memory Block 0101h Free DOS Memory Block 0 102h Resize DOS Memory Block INTERRUPT MANAGEMENT SERVICES 0200h Get Real Mode Interrupt Vector 0201h Set Real Mode Interrupt Vector 0202h Get Processor Exception Handler Vector F amp EF KF OF amp amp amp amp amp amp F Ee OF OK F xXx amp Fe FH He KE HE HE HEH KF HE HR KR KH OX DPMI Services 387 Function Function DPMI 0203h Set Processor Exception Handler Vector 0204h Get Protected Mode Interrupt Vector j 0205h Set Protected Mode Interrupt Vector 0210h Get Extended Processor Exception Handler Vector in Protected Mode 021 Ih Get Extended Processor Exception Handler Vector in Real Mode 0212h Set Extended Processor Exception Handler Vector in Protected Mode 0213h Set Extended Process Exception Handler Vector in Real Mode 0900h Get and Disable Virtual Interrupt State 0901h Get and Enable Virtual Interrupt State 0902h Get Virtual Interrupt State TRANSLATION SERVICES 0300h Simulate Real Mode Interrupt 0301h Call Real Mode Procedure with Far Return Frame 0302h Call Real Mode Procedure with Int Return Fram
416. oth IN and OUT instructions and shows that they work tine from Protected mode subject to the above mentioned caveats Real time While we are on the subject of timers another issue arises that of events synchronisation or response with or to real time events An interrupt from a hardware timer is a real time event Any hardware interrupt is a real time event Real time need not necessarily imply external hardware if one application wants to signal another and if the other is to respond immediately it will be a real time response It may be that an external device has to signal a Windows application and it may be important that the application respond in a very predictable way within a predictable time frame Unfortunately Windows response is anything but real time This iS a very important issue and worthy of a new chapter Windows A little note before I launch into the real time section Windows timers does have software timers that can be programmed to time out at regular periods just like the hardware timers discussed above See the usage of SETTIMER on pages 239 However upon time out they send a message to the application over the standard message queue so its arrival time at the application is highly unpredictable It is even possible for the timer to time out a few times and queue the messages before the application gets them suddenly the application will get three or more timer timeout m
417. other thought how do you access data in DS the data segment This is the place to keep data so obviously your program must be able to get to it Simple most instructions automatically reference the DS For example the listing below shows how VALI is defined and referenced DATA VAL1 DB 0 in data segment CODE mov ax VAL1 in code segment Later you will see more details on how to use the assembler so don t worry about that side of things Suffice to say that you can define a label in the data segment and reference it from the code segment When the program is assembled the address of VALI will be put into the operand of the MOV instruction note however that this is an offset relative to the DS Most importantly when your program is executed it must have DS set to the beginning of the data area as the MOV instruction will automatically use DS to compute the physical address Sometimes especially with pop up and interrupt routines the program may be entered with DS not set correctly so you have to take care of that at the beginning of the program Segment Although the MOV instruction in the above example automatically override referenced the DS register it is possible to override this For example you could have data in the code segment so your program would have this DATA CODE jmp placel VAL1 DB 0 data defined in code segment placel mov ax cs VAL1 COM format ES register Concept of the
418. ou want reusable and maintainable code Do you want to program faster and debug faster Then go for objects In a nutshell OOP is just the use of structures In C the STRUCT declaration is almost exactly the same as CLASS The reason is very simple a class is only a structure with some bells and whistles Look back to page 65 to clarify what structures are and how they are used and youve already grasped the principle of objects Objects are just instances of a structure or the actual copies of the structure that are created In Chapter 5 I used structures in a skeleton program OOP terminology is what confuses everything In the second half of this chapter I have shown the impressive power of OOP when applied to assembly language but for now you need to know a few basics Object Addressing C has a lot of terminology that can be very intimidating Yet the underlying concepts are quite simple It is also quite true that you can read an explanation from a C manual or textbook a dozen times and not fully grasp it But if you were to see how that concept is implemented at the assembly level it would become clear This is one reason why I am in favour of this book being used as a prerequisite not just to Windows but also to C programming The way we write a program using 00 techniques is by grouping data and code that naturally belongs together into a class structure definition A structure need not contain just da
419. our program plays a very passive role taking whatever Windows dishes out With Windows there is a system queue and an application queue for each application Our program calls Windows and asks for the message at the head of our application s queue or waits until a message is put into the queue Returning from the call our program then deciphers the message and acts upon it There are some little wrinkles in this basic explanation but that s the gist of it Technically Windows 3 x has one application queue for all applications while Windows 95 32 bit applications have separate queues This does not affect the programmer It is an issue for Windows itself with regard to scheduling of applications Another major conceptual change is due to the multitasking nature of Windows Unlike DOS where everything usually stays put after it is loaded code and data can move around Even video RAM cannot be treated as being at a particular address although it actually is an application may have to output to a logical video 72 Windows Assembly Language amp Systems Programming buffer located somewhere else Consider another example the heap You can request local or global heap space this is just memory that you can use for storing data but unlike single tasking DOS you cannot just get its address and then write to it The heap could be moved around by Windows though you can freeze things also These shifting sands impose co
420. out uses a flowchart model of programming in which the programmer interconnects modules representing flow of control as shown in Figure 15 4 The representation is different from conventional flowcharts as you can see in the way the repeat loop is constructed The little arrows going off to the left point to 364 Windows Assembly Language amp Systems Programming Visual efficiency Target market subroutines or procedures and clicking on one of those little boxes brings up the subroutine flowchart The flowchart concept is ancient and its popularity comes and goes Modem flowcharts do need constraints unlike the old representations that we oldies used with Fortran that allowed spaghetti code Layout also forces some concurrency mechanisms such as being able to send a message to a procedure and have the procedure execute concurrently Layout also allows flowcharts to be attached to specific objects on a window so for example if you press a button on the screen the attached code will execute asynchronously to the rest of the application However the way in which the flowchart paradigm has been forced into these avenues is to me very odd Comparison with LabView Layout on screen graphical program construction representation is very crude and cumbersome compared with LabView The flowchart just about immediately fills the screen and you have to scroll a long way down to see everything Of course a tight hierarchy he
421. ow but you are still employing super fast direct access to the video RAM Yes you can have your cake and eat it too By getting a selector to the video RAM you can write directly to it But what about virtual video RAM Since we are running in virtual machines shouldnt output to the video RAM be to a virtual video RAM that does not necessarily correspond with the physical video RAM This is potentially true but all WinApps run in the system VM and the virtual video RAM does correspond to the physical I am perhaps getting a bit ahead here Even though the concept of a VM was introduced in Chapter 1 I havent fully developed it until Chapters 10 11 and 12 A DOSApp running in another VM does write to a virtual video RAM which Windows can map directly to full screen or into a window depending upon the settings of the PIF file The problem with the above overwriting the current Windows screen is that when you exit your callback and return control to Windows the screen will be redrawn Of course you may not want to return to Windows until you have finished running your game or whatever but suppose you do A return to Windows without redrawing the screen can be done by not executing INT 3 1h AX 4002h or REPAINTSCREEN 238 Windows Assembly Language amp Systems Programming Dumping the queue PEEK MESSAGE DOS keyboard mouse input These can be executed later when the time is right or not at all Message
422. ow it lets the callback know by sending WM_PAINT This is so the callback can redraw the client area or the portion that requires redrawing The UPDATEWINDOW function also generates a WM_PAINT message I wanted to put out a simple text message in this case Demo 00 Program It also uses the font that I previously got a handle for rather than the default font There is a bit of red tape involved to output the message and some temporary data storage is required hDC is the handle to the windows client area that is the area of the window that we can output to and this handle must be obtained before we can gain access to the window client area It is normal practise to release this handle immediately after use which has been done by ENDPAINT The other thing I did in my skeleton was respond to the File menu item with its Quit and About sub items The normal way to define these is by the resource file RC and I have used exactly the same one as before The WM_COMMAND message needs to have its Iparam and wparam analysed to determine what kind of command has been sent to the callback and this example 158 Windows Assembly Language amp Systems Programming shows that if Iparam 0 then the command has come from the window menu bar In such a case wparam is analysed to see which item has been selected from the menu bar Handling Notice that selection of Quit results in calling destroy
423. owing format Offset Length Contents 00h 4 DI or ED1 04h 4 SI of ESI 08h 4 BP or EBP OCh 4 reserved should be 0 10h 4 BX or EBX 14h 4 DX or EDX 18h 4 CX or ECX ich 4 AX or EAX 20h 2 CPU status flags 22h 2 S 24 2 DS 26h 2 FS 28h 2 GS 2Ah 2 IP reserved ignored 2Ch 2 CS reserved ignored 2Eh 2 SP 30h 2 SS Returns if function successful CF clear ES E DI selector offset of modified Real mode register data structure if function unsuccessful CF set AX error code 80 12h linear memory unavailable stack 80 13h physical memory unavailable stack 8014h backing store unavailable stack 8021 h invalid value CX too large 394 Windows Assembly Language amp Systems Programming Int 31h Function 0301h Call Real Mode Procedure With Far Return Frame Simulates a FAR CALL to a real Mode procedure The called nrocedure must return by executing a RETF far return instruction Call with AX 0301h BH flags Bit Significance 0 reserved for historical reason must be zero 1 7 reserved must be zero cx number of words to copy from Protected mode to real mode stack ES E DI selector offset of real mode register data structure in the following format Offset Length Contents 00h 4 DI or EDI 04h 4 SI or ESI 08h 4 BP or EBP OCh 4 reserved ignored 10h 4 BX or EBX 14h 4 DX or EDX 18h 4 CX or ECX ICh 4 AX or EAX 20h 2 CPU status flags 22h 2 ES 24h 2 DS 26h 2 FS 28h 2 GS 2Ah 2 IP 2Ch 2 CS 2E
424. panion Disk Although VxD Lite targeted Windows 3 1 systems the VxDs will run fine in Windows 95 a VxD is a VxD You can find VxD Lite bundled with Writing Windows Virtual Device Drivers by David Thielen and Bryan Woodruff Addison Wesley 1994 Although this book is still in print the publicity does not mention VxD Lite as one of the authors works for Microsoft I fear the worst Locate an older copy somewhere LS Advanced Systems Programming Preamble Other Chapter 12 shows how a 16 bit Windows application WinApp chapters can access 32 bit ring 0 code Chapter 13 shows how to construct a pure 32 bit ring 3 WinApp Chapter 14 shows how DOS applications DOSApps Winapps and Virtual Device Drivers VxDs can communicate In Chapter 14 the communication is established by the DOSApp while Windows loads Much of this book has described how BIOS and DOS interrupts plus the interrupt extensions 31h and 2Fh in particular provided by Windows can be used However this is all from the viewpoint of a 16 bit DOSApp or WinApp Execution of an interrupt causes a processor exception and the Windows handler is in most cases in a 16 bit segment Therefore a 32 bit WinApp cannot use the interrupt services even though they are there and likely to stay there for future versions of Windows Just as Chapter 12 shows an application going from a 16 bit segment to a 32 bit segment called thunking it is necessary for a nati
425. pmiversion DW O ah major al minor 386modeflag DB 0 1 386 dpmi type realmodeintsflag DB O0 1 Real mode interr virtualmemflag DB 0 j l virt mem support cputype DB 0 2 3 4 286 386 486 CODE mov ax 1686h Xtest if dpmi running int 2Fh Or ax ax jnz nodpmi mov dpmiflag 1 set flag dpmi ok mov ax 0400h get dpmi version int 31h mov dpmiversion ax mov al bl and al 01 bit 0 1 if 386 dpmi mov 386modeflag al mov al bl shr al l and al 01 jbit 1 1 if not virtual86 int handling mov realmodeintsflag al shr bl 2 and bl 01 bit 2 1 if virtual mem supported mov virtualmemflag bl mov cputype cl cl 2 3 4 if 286 386 or 486 Refer to Appendix C for a full description of all DPMI services INT 2Fh AX 1686h is used to check if the CPU is running DPMI and is in Protected mode This service returns a false flag if Windows is loaded in Real mode or DPMI is not running You would only need to perform this check if you were running Windows in Real mode but version 3 1 of Windows wont even run in Real mode so these days this test isnt required Which version of DPMI is run fling Direct access to memory and video RAM Text mode Windows applications Direct Hardware Access 227 Note that most of the INT 2Fh services work in Real and Protected mode with or without DPMI but INT 3lh will only work with DPMI and in Protected mode The next service is INT 3 1h AX 0400h which returns the DPMI version number
426. pplications there is And here is the other WINDOWS INC and ese ae WINASM60 INC and for 32 bit clsLpfnWndProc DD applications there is W32 INC clsCbClsExtra DW clsCbWndExtra DW clsHInstance DW There is also an extended window ee sHIcon ee class with a structure called clsHCursor f clsHbrBackground DW WNDCLASSEX that has an extra clsLpszMenuName DD field It is used with REGISTERCLASSEX clsLpszClassName DD WNDCLASS ENDS Now back to the program listing High Level Assembly 115 hPrevinstance 0 0 if no previous instance yeslst createwin the window class structure for REGISTERCLASS sl clsStyle 3 s1 WORD PTR clsLpfnWndProc OFFSET WinasmlProc s1 WORD PTR clsLpfnWndProc 2 SEG Winasm1Proc sl clsCbClsExtra 0 sl clsCbWndExtra 0O ax hInstance sl clsHInstance ax LOADICON PASCAL null O IDI_APPLICATION sil clsHIcon ax LOADCURSOR PASCAL null O IDC_ARROW sl clsHCursor ax s 1 elsHbrBackground COLOR BACKGROUND ax OFFSET szwinasmliname s1 WORD PTR clsLpszMenuname ax S1 WORD PTR clsLpszMenuName 2 ds s1 WORD PTR clsLpszClassName ax 1 WORD PTR clsLpszClassName 2 ds Registering The above block of code is setting up the data structure prior to a window calling REGISTERCLASSO Compare that with the previous program page 99 You will see there that we had to explicitly access the stack segment between bp and bp 46 in which the instance of the structure was kept
427. produced below is the portion of the installation code that sets up the data structures required for auto loading of the VxD and WinApp A vital point must be brought out now I chose to put the TSR TSR2WIN EXE inside the VxD as a DOS stub All Windows programs have a DOS stub which is a DOS program that resides inside the Windows program Should the user execute the Windows program from the DOS prompt only the stub will execute It is usual for the DOS stub to display a simple message that you need Windows to run this program then it terminates Putting the TSR inside a VxD is easy I have placed a typical DEF file used for linking a VxD in directory TSR2WIN and this file is called VDEMOD DEF It shows how easy it is to specify the TSR as a stub to the VxD It is not essential to do this but it offers a simplification for the TSR to automatically load the VxD the TSR needs to know the path of the VxD If the path is fixed then you can specify it in the TSR or maybe you could pass it to the TSR on the DOS command line tail when loading the TSR Or by having the TSR inside the VxD the TSR need only look at its own path to determine where the VxD is It was an arbitrary choice but I chose to put the WinApp in another directory and have specified the path in the TSR but I could have also put the WinApp in the same path as the VxD 332 Windows Assembly Language amp Systems Programming Start of TSRZWIN TSR TSR2
428. ptor tables The CPU has various extra registers for maintaining the paging mechanisms most importantly CR3 which contains the base address of the Page Table Directory Just for the record The address computed from the descriptor table now renamed the linear address as it is no longer the final physical address is divided into fields with bits 22 to 31 being an index into a page table directory that gives the address of a particular page table Bits 12 to 21 are the index into this second table which contains the final address Bits 0 to 11 are unchanged and become part of the final address You will come across the words linear address later in the book Note that sometimes the words virtual address are used in various books to mean the same thing though there is a distinction The linear address is that 32 bit address that would be the physical address if page tables didn t get in the way Virtual 86 This is another paging mechanism that does away with descriptor tables It was intended to provide the 386 with better Protected mode emulation of the 86 CPU than the 286 can manage which it does very well 30 Windows Assembly Language amp Systems Programming This mode is fascinating It also does away with selectors and brings physical segment paragraph addresses back into the segment registers Thus we come full circle but with a vital difference Paragraph Although the 16 bit segment address is back and once
429. push ax sub ax ax type of window 32 bit value mov dax 207 push dx push ax i mov ax 150 x coord 16 bit push ax sub ax ax y coord 16 bit push ax mov ax 250 width 16 bit push ax j mov ax 200 height 16 bit push ax The Bare Bones 101 sub ax ax push ax O no parent for this window push ax O use the class menu mov ax WORD PTR bp 12 hInstance push ax sub ax ax push ax O no params to pass on push ax 32 bit long pointer call CREATEWINDOW mov WORD PTR bp 2 ax returns hWnd in AX handle to the window Here we save it temporarily push ax ShowWindow requires hWnd push WORD PTR bp 4 and nCmdShow on the stack call SHOWWINDOW Tells Windows to display window push WORD PTR bp 2 hWnd call UPDATEWINDOW tells Windows to redraw now jmp SHORT messageloop go to the main message loop Message Refer back to page 77 for an explanation of the message loop The loop event driven nature of a Windows application means that GETMESSAGEDO goes to Windows and waits for a message from the queue After return key presses are preprocessed by TRANSLATEMESSAGE then control is passed to the callback function via DISPATCHMESSAGE and Windows mainloop lea ax WORD PTR bp 20 far addr of message push ss eo push ax p f call TRANSLATEMESSAGE lea ax WORD PTR bp 20 far addr of message push ss push ax i call DISPATCHMESSAGE P lea ax WORD
430. r you can achieve the same results with different syntax e Im not so sure about passing dynamic data parameters to high level PROC declarations If you specify a parameter OFFSET S1 it means pass the address of S1 However that works if the data is declared statically in the data segment For data declared by the LOCAL directive that is dynamic stack based data it seems to be necessary to load the data into a register first and pass the register as a parameter MASM doesnt have this limitation with its ADDR directive Installing TASMS Alf the TASMS is designed to work from the command line in a DOS box TASM5 tools There is no editor or IDE There is though the wonderful Turbo are DOS Debugger I prefer to use the command line though an IDE does programs have advantages such as seeing where assemble errors occur in the source code With the command line approach the assembler spews out a list of errors and the developer must then find those lines in the source code which is easy enough C gt make B DDEBUG more If the assembler generates a huge error listing this is what you do to make output fill the screen and pause Simple enough The make program will execute makefile if it existes otherwise a filename needs to be entered on the above command line after the switches B means to rebuild everything DDEBUG is interpreted inside the Make file to include debug information The
431. r eup 185 INterrunt deflection to Real mode 268 Interrupt Descriptor Table IDT 34 Interrupt gate 292 Interrupt handlers 320 Interrupt Vector Table IVT 33 INTERRUPTREGISTER 213 Interrupts hardware 256 Interrupts hardware versus software 250 Interrupts hooking 200 250 Interrupts protected mode 34 Interrnpts Real mode 31 Interrupts software 31 INTERRUPTUNREGISTER 213 INVOKE high level call 127 IRET instruction 34 IRQ Interrupt ReQuest 185 IRQO to IRQ7 185 256 IRQO to IRQ 15 256 ISA bus 188 ISR accessing data in 253 ISR Protected mode 321 ISR Real mode routine to call 324 ISR reentrancy 323 IVT 33 185 268 J JMP instruction 40 42 Jump instructions 39 Jx conditional instructions 40 43 K KERNEL EXE 72 207 Keyboard driver functions 217 Keyboard interface 184 KICKSTARTO 00 program 153 KILLSYSTEMTIMER 217 KILLTIMERQ 241 L Labels code 4 Labels code amp data 56 LabView 359 Late binding Layout LDT in a VM LDT purpose of LEA compared with OFFSET LES LDS amp LEA instructions LES with data label operand Library functions Linear address Linking LOADCURSOR Q LOADICON LOADLIBRARY LOADMODULE LOCAL data Local Descriptor Table LDT LOCAL directive LOCALFIRSTQ LOCALINFO LOCALNEXT Q LOCALS directive LOCKINPUT LOCKSEGMENT LODS x instructions Logical instructions LOOP instruction Loudspeaker control lParam Machine cycle Machine Status Word MAKE 00 progra
432. r if it is called as a function member from C code Fortunately there is an easy way to figure out the interfacing requirements between C or C or any other language and assembly language and that is to utilize the compilers ability to generate assembly language output Compiling to ASM O P Most high level compilers will do this by means of a switch on the command line The compiler will produce an assembly language listing of the C program showing the exact correspondence of lines of C to the equivalent assembly code This is highly educational but it is particularly useful for linking between C and assembly 148 Windows Assembly Language amp Systems Programming Compile a ASM stub Name mangling class The trick is to write the assembly language module into the C program in the form of a stub or skeleton That is it wont do anything except have the data transfer C instructions Compile it and look at the assembly listing for that routine Extract that routine into a separate assembly language tile and delete the original stub This works fine and is surprisingly easy to do The method overcomes some serious hurdles especially that of name mangling It is a C feature that the source code can have the same name for different functions and other labels can also have identical names The compiler gets around this problem by mangling the labels applying an algorithm so that even labels of the same name
433. r location on that chip PC Hardware 183 There are three address lines into the decoder in this example Al 7 to A19 Say that the decoder is designed to detect an input of 101 binary BITE TY L8 T7 16 L5 TA xF3 12 a A ie oe ee IO T OIO 0 0 OO Oh OO cd 1 0O 1 1 1 1 1 1 1 1 1 1 1 1 This means that the RAM chip occupies address range A0000h to BFFFFh and the size of the RAM would have to be 2 17 128K bytes I O Ports If you peek back at the diagram of the control bus for the CPU Figure 7 1 you will see that there are a couple of lines called IOR and IOW These are for reading and writing I O ports Unlike some CPUs such as the 6800 family that do not distinguish between memory and I O operations the Intel 86 family have special instructions and special control lines for I O Figure 7 4 is a typical I O circuit Notice its similarity to the memory interface shown in Figure 7 3 A major difference is that IOR and JOW go to it instead of MEMR and MEMW Figure 7 4 Interface CPU to I O port ALE CS Detects the address range of the RAM AQ A19 Address chip SO has the address bus decoder hig er order address bits as Input Port A IOR IOW data bus Port C Port B Whenever the CPU executes a read port instruction IN it performs an I O read machine cycle that looks just like the timing diagram for memory access except IOR gets pulsed low Now we have fully answered the que
434. r way and again the IVT is an excellent avenue However I have been describing above the concept of multiple virtual machines each with its own IVT TSRs and DOSApps The big question now is how do we know which IVT and DOS program we are accessing from our WinApp To answer this question read on DOS TSRs Concept DOS TSR Terminate and Stay Resident programs which also of TSRS include device drivers are covered in many DOS programming books They load like any other program but only have a short install procedure then exit back to DOS The exit is via a special DOS service that leaves the program resident in memory rather than freeing up that memory space as with normal programs TSRs usually hook a vector such as INT 8 9 or 16h For example by hooking INT 16h or 9 all DOS keyboard input can be filtered Usually the TSR passes control to the old vector after doing whatever it wants Once a TSR is loaded and control returns to DOS you can then load another program so even under single user and single tasking DOS you have two or more programs sitting together in memory The TSR will be executed or rather its run time portion will be executed whenever the particular interrupt is called The Companion Disk has a useful TSR skeleton that hooks INT 16h with many of the tricks of the trade incorporated into it fully commented for your convenience Look in DOSTSR A TSR sits If you load th
435. ra 64K is peanuts The 286 has 24 address lines and can theoretically have 2 bytes of memory which is 16M The 386 has 32 address lines allowing 4 3 gigabytes G But all of this is inaccessible with the CPU in Real mode Or is it Later in this book you will see that 386 and later processors can access the entire 4 3G from Real mode DOS Real Mode Programming DOS itself the DOS and BIOS I O services DOS applications device drivers and TSRs are all designed to work in Real mode This is because they rely on real addresses being in the segment registers Consider an example A programmer could use the ES register to write directly to the video RAM Video RAM is just like any other RAM except that what you store there appears on the screen also A programmer could load B800 hex into ES which will address the CGA video RAM i e the full 20 bit starting address for the segment will be B8000 hex In assembly language the programmer writes an instruction like Mov ES DI AL or STOSB to store a value from general purpose register AL to the address ES DI Note that the terminology ES DI refers to the address in the form of segment offset ES is the segment and DI or some other 16 bit register has the offset DI and AL would both need to be loaded beforehand of course The point here is that the program loads an actual segment address into ES This reliance upon real values being in the segment registers means that DOS progr
436. rd for many people to grasp which is why I tended to delay this little detail until later in the book So whenever we communicate with Real mode from a Windows program running in Enhanced mode we are only communicating with a simulated Real mode that is a virtual 86 machine The 1M address space of this machine will in reality be mapped via paging to anywhere in RAM that the operating system decides The virtual addresses may map to the same physical addresses see page 343 for more detail on this When Windows is running in Enhanced mode and you load a DOS program Windows will create a virtual machine just for it You could in fact load any DOS program including a TSR Another way to do this is to go to the DOS prompt from within Windows and load the program from there A TSR loaded in this way will sit inside the virtual machine and will only be usable from within that virtual machine This is a vital point Tt is this feature that enables Windows Enhanced mode to multitask DOS applications in Windows not only full screen as required by Standard mode Real Mode Access 273 Earlier I described how to call a Real mode ISR directly by a DPMI service I also explained that any BIOS or DOS service can be called by a software interrupt INT n which is reached via the IDT and IVT Accessing a TSR via the IVT is a very convenient avenue for getting at Real mode code and data Later on in the chapter I look at going the othe
437. rder of values with the lowest byte at the lowest address The same goes storage of for FAR addresses the offset always comes first that is at the data in lowest address memory In the above code I suffixed the values with h to indicate that they are hexadecimal values not decimal The memory would look like Figure 2 8 after assembly Always remember the lowest byte at the lowest address Basic Assembly Language 65 Figure 2 8 Order of storage Offset in dat segment of ptroffset Offset in data segment of A 34h p amp segment Increasing addresses 4 Structures Whatever language you have experience with you have probably encountered the concept of data structures These are in fact the foundation of object oriented programming OOP Windows programming makes extensive use of data structures so it is appropriate to introduce the topic here DATA WINDOW STRUC Definition of structure fieldil DB ABCDEFGHIJ field2 DW 0O field3 DD 0 WINDOW ENDS EAO Assembling instances win1 WINDOW lt KLMNO 35 0 gt win2 WINDOW lt PQRSTUVWX 55 234 gt CODE Accessing the instances mov ax winl field2 mov si OFFSET winl mov ax si field2 mov ax si 10 66 Windows Assembly Language amp Systems Programming Object oriented programming Instances Dot operator This listing shows how a structure is declared and used In OOP terminology the definition is the cla
438. re the array must be set to zero Each Instance_Item_Struc structure specifies the starting address and size in bytes of an instance data block The device driver or TSR must copy the address of its startup structure to the ES BX register pair before returning See also at end of this appendix Win386_Startup_Info_Struc Instance_Item_Struc INT 2F Extensions 405 Interrupt 2Fh Function 1606h Windows Termination Notification Notifies MS DOS device drivers and TSRs that standard or 386 Enhanced mode Windows is terminating Windows calls this function as it terminates allowing MS DOS device drivers and TSRs that monitor Interrupt 2Fh the opportunity to prepare for leaving the Windows environment Call with AX 1606h DX Specifies whether standard or 386 Enhanced mode Windows is terminating 386 Enhanced mode Windows sets bit 0 to 0 standard mode Windows sets bit 0 to 1 Only bit 0 is used all other bits reserved and undefined Return value This function has no return value Comments Windows calls this function when the processor is in Real mode Interrupt 2Fh Function 1607h Device Call Out Directs an MS DOS device driver or TSR to provide information to the calling virtual device Although the BX register specifies a device identifier other registers may be used to specify the action to take Called with AX 1607h BX device identifier for a virtual device Return value The return value
439. return value Comments When a virtual machine is in a critical section no other task will be allowed to run except to service hardware interrupts For this reason the critical section should be released using End Critical Section Interrupt 2Fh Function 1682h as soon as possible Interrupt 2Fh Function 1682h End Critical Section Releases the critical section previously started using Begin Critical Section Interrupt 2Fh Function 168 lh Every call to Begin Critical Section must be followed by a matching call to End Critical Section Call with AX 1682h Return value This function has no return value Interrupt 2Fh Function 1683h Get Current Virtual Machine ID Returns the identifier for the current virtual machine MS DOS device drivers TSRs and INT 2F Extensions 407 other programs use this function to determine which virtual machine is running This is especially important for programs that independently manage separate data or execution contexts for separate virtual machines Call with AX 1683h Return value The return value is the current virtual machine identifier in the BX register Comments Each virtual machine has a unique nonzero identifier Although Windows currently runs in virtual machine I programs should not rely on this Windows assigns the identifier when it creates the virtual machine and releases the identifier when it destroys the virtual machine Since Windows may reuse identifi
440. riptor for the current LDT it puts this into the corresponding shadow register alongside the LDT register so from then on until a task switch or until the LDT changes position the CPU will know where the LDT is without having to reread the GDT Figure 1 12 Association between descriptor and shadow register CPU Architecture 27 Figure 1 12 Memory management 386 CPU 15 Actual memory This is the internal segment registers LDT task 1 selectors CS DS aaa etc 0 if pointing to the GDT 1 if pointing to LDT task 2 an LDT rpl requested task 3 ete privilege level Each entry in an LDT or the GDT is called a program segment descriptor amp has the es data code or stack address of a segment The next step in this saga is that the CPU can use the selector in the CS register to index into the current LDT and get the actual address or more correctly the descriptor of the code segment The IP register or EIP will have the offset into that segment from which the CPU will fetch the instruction Having read the descriptor from the LDT the CPU then has the base address of the code segment To avoid having to look in the LDT every time it wants to fetch the next instruction the CPU makes use of shadow registers again Every segment register has an associated shadow register 28 Windows Assembly Language amp Systems Programming The CPU will only have to look in the
441. ro Returns if function successful CF clear BX CX linear address of allocated memory block memory block handle used to resize and free block if function unsuccessful SIDI set AX error code 8012h linear mem unavailable 8013h physical mem unavailable 8014h backing store unavailable 80 16h handle unavailable 8021 h invalid value BX CX 0 Int 31h Function 0502h Free Memory Block Frees a memory block that was previously allocated with either the Allocate Memory Block function Int 31 h Function 0501h or the Allocate Linear Memory Block function Int 31h Function 0504h Call with AX 0502h SI DI memory block handle Returns if function successful CF clear if function unsuccessful CF set AX error code 8023h invalid handle Int 31h Function 0503h Resize Memory Block Changes the size of a memory block that was previously allocated with either the Allocate Memory Block function Int 31h Function 0501h or the Allocate Linear Memory Block function Int 3 1h Function 0504h Call with AX 0503h BX CX new size of block bytes must be nonzero SI DI memory block handle Returns if function successful CF clear BX CX new linear address of memory block new handle for memory block if function unsuccessful CF set AX error code 8012h linear memory unavailable 8013h physical memory unavailable 80 14h backing store unavailable 8016h handle unavailable 8021h inv
442. rotected mode ISR The DPMI Toolkit available from Qualitas see http www qualitas com has mechanisms for this In your DEF file FIX the code segment in place and do not mark it as DISCARDABLE This will not stop Windows from removing the segment from memory but whenever your program needs to access the segment it will be reloaded into the same place well nearly always If you get a selector alias to store data into the code segment such as a window handle to be used by the ISR or even the alias itself for writing data to the code segment within the ISR it will work The alias will not require updating because the code segment marked as FIXED in the DEF file will remain at the same place in 324 Windows Assembly Language amp Systems Programming Bolting the segments down and the wayward data segment Some philosophic points about DOS drivers Using up the first 1M of physical memory memory even though Windows may temporarily remove it The potential problem here is that Windows does not think that you should be writing to the code segment so will never swap it out Instead it is just dumped and when needed again it is copied from the original on disk so you lose your data If you look at the above listing on the Companion Disk youll see that I used GLOBALHANDLEQ and GLOBALFIX The first returns a handle for a selector or segment address while the second Windows funct
443. roups of functions it can perform Controlling Port 60h is now capable of sending commands mostly directed to the 8031 the 803 1 controller on the actual keyboard and 8042 Port 60h can also be used to receive other data which works in conjunction with port 64h Basically port 64h is for sending commands to the motherboard 8042 controller and if any of those return data it is read at port 60h Therefore you use these two ports in a particular sequence an OUT to port 64h followed by an IN from port 60h Status of Port 64h can also be read and it provides status information about the 8042 the 8042 or whatever chip is being used as the AT class motherboard keyboard controller as shown in Table 7 1 How to read A most important point that you should note from Table 7 1 is that and write you must test bit l before performing any OUT to ports 60h or port m amp 64h and you must test bit O before doing an IN from port 60h 64h In fact a curious piece of information is that on a Type 1 MCA PC you must wait seven microseconds after bit O becomes logic l before reading port 60h MCA is IBM s own proprietary expansion bus system Fortunately it implements ports 60h and 64h much the same as in AT machines MCA is just about history Testing for the XT model Further references PC Hardware 187 Table 7 1 Port 64h input MEANING Parity error on serial link from keyboard 1 Receive timeout error from keybo
444. rrupt BX iCall with AX 0200h BL interrupt number Returns CF clear this function always succeeds CX DX segment offset of real mode interrupt handler Int 31h Function 0201h Set Real Mode Interrupt Vector Sets the current virtual machine s Real mode jinterrupt vector for the specified interrupt Call with AX 0201h IBL interrupt number CX DX segment offset of real mode interrupt handler Returns CF clear this function always succeeds Jint 31h Function 0202h Get Processor Exception Handler Vector JReturns the address of the current client s Protected mode exception handler for the specified exception number This function should be avoided by DPMI 1 0 clients Call with AX 0202h BL exception number 00h 1 Fh Returns if function successful CF clear CX E DX selector offset of exception handler if function unsuccessful CF set AX error code 802 Lh invalid value BL not in range O I Fh Int31h Function 0203h Set Processor Exception Handler Vector Sets the address of a handler for a CPU exception or fault allowing a Protected mode application to intercept processor exceptions such as segment not present faults that are not handled by the DPMI host and would otherwise generate a fatal error This function should be avoided by DPMI 1 O clients Call with AX 0203h BL exception fault number 00h 1Fh CX E DX selec
445. rts I O 183 POSTMESSAGEQ 259 POSTQUITMESSAGE 105 Power on address 10 Power on steps PRESTOCHANGOSELECTOR 21 Private amp global data 120 Privileges PROC high level Ls PROCDESC modifier 308 Process32First Q Process32Next Programmer s WorkBench Prolog code Protected amp Real modes Protected mode interrupts PROTO declaration Prototypes PTR modifier PUSH instruction PUSHF instruction Quick assembler version 2 01 QWORD 64 bit R Radix Real mode 32 bit Real mode register structure Register addressing mode Register initialisation REGISTERCLASS Registering a window Registers CPU Registers 32 bit REP prefix REPAINTSCREEN Resource file RESTORESCREEN RESURRECTIONO RET number instruction Ring transition Ring O 32 bit code Ring O stack Rings Rotate instructions S SAVESCREEN SBB instruction SCASx instructions Scope label differences SEG override Segment bolting it down Segment override Segment registers initialisation Segmenr registers using Segments fixed versus moveable Segments how started SELECTOBJECT Q SELECTORACCESSRIGHTS Selectors SENDMESSAGE SETSELECTORBASE SETSELECTORLIMIT SETTIMER SETWINDEBUGINFOQ SETWINDOWSHOOK Index 417 215 291 18 45 100 1 100 9 22 24 22 48 211 231 234 74 89 218 211 236 40 291 299 298 55 418 Windows Assembly Language amp Systems Programming SETWINDOWWORD 169 Sha
446. rty two bits gives us an enormous addressing capability 4 3 thousand million bytes gigabytes Note that for compatibility reasons each address actually addresses 8 bytes of data in memory even though the data bus is 32 bits Addressing of I O ports is still the same as for the 88 86 286 using the lower 16 bits of the physical address bus coordinated with the IOR and IOW control lines 16 bits allows up to 65 536 I O ports It is important to note that the I O address space is separate from the 4 3G memory address space this differs markedly from the Motorola 68000 family in which there is no separate I O space I O ports are accessed by the IN and OUT instructions see page 244 Figure 1 10 386 32 bit address and data 386 CPU Memory Instruction Ptr possible 32 bit address bus js 4 3G data _ gt bus CPU Registers Obviously if the 386 is to be downwardly compatible it must have the same registers as its older relatives and yes they re all there AX BX CX DX SI DI BP and SP are the 16 bit registers inherited from the 86 and 286 Incidentally the 286 has the same register set as the 86 plus some extra ones for managing Protected mode Itis only with the 386 that significant enhancements of the registers occur they are all 32 bits except for the segment registers It is important to understand that the registers you can use in an application can be used as 32 16 and in some cases 8 bit regis
447. rupt occurs and if the interrupt is one of the BIOS DOS services Windows will redirect control down to Real mode and the routine pointed to in the IVT in the system VM Therefore if you want your interrupt routine to work for the CPU in both Real or Protected mode especially in the case of hardware interrupts why not use functions 0303h and 0201h to hook only the IVT and have just one ISR This will work for all normal DOS interrupt services which do get redirected from the IDT to the IVT Unfortunately the particular case of INT 9 which we have been using as a case study does not get redirected in this way This deviates somewhat from my current line of thought For more on handling hardware interrupts refer to Chapter 12 The DOSApp Signaller Whenever a V86 machine is created it will be in response to loading a DOSApp This DOSApp may want to send a message to a WinApp so it will need some code inside it to call the forwarder routine in the DOS TSR This is how the section of code would look DOS signaller program what follows is only a fragment of the whole DOSApp DATA ivt6 lof ivt61lseg tsrloaded CODE mode Ne Ne we j here already s e DW 0 address of forwarder in DOS TSR DW 0 DW 0 set if TSR has hooked int 6lh Test if Windows was loaded in Enhanced or Standard the method for doing this is shown in Chapter 12 I have just supplied a flag winmode
448. s plus the use of low level Windows functions I have pointed out overlap between the two where it occurs You will be amazed to learn that it is possible to have an application running in a window yet the application can write directly to the video hardware at breathtaking speed without all of the Windows rigmarole This is the kind of practical code developed in this chapter You will also learn about I O aspects such as use of the IN and OUT instructions Mostly I view the material of this chapter as educational It pokes around doing fun things that may be viewed as hacking It may be that you will never use some of the less orthodox material in professional applications but what will be formed now is a good solid foundation of understanding of the fundamentals 225 226 Windows Assembly Language amp Systems Programming Initialisation Is DPMI First 1 11 address the question of initialisation Since your program available is running in Protected mode alongside other programs you cant simply go reading and writing all over memory and I O There have to be rules to prevent contention Initialisation is code that clears the way for you to get directly at the hardware The code below is a good way to start For the moment dont worry about the red tape of PROC ENDP etc Youll put it together later Before you can use DPMI services you need to check out a few things DATA dpmiflag DB O 1 dpmi running ok d
449. s 3 x and 95 because all WinApps run under the same LDT but beware Windows NT The word of warning here is that if you want your selectors to be global across 32 bit Windows NT applications which will run with private LDTs then put your selector into the GDT 338 Windows Assembly Language amp Systems Programming Now for the part that actually loads the VxD and WinApp TSR Resident Code INT 2Fh The resident code monitors IVT 2Fh and detects when Windows is handler loading as follows runtime2F entered when Windows loads with AX 1605h and when Windows unloads with AX 1606h detect when Windows loads and set a flag sti documentation says this req d cmp ax 1608h Enhanced mode loaded jne nexttry mov e s winloaded 1 jmp SHORT go2F nexttry cmp ax 1605h test if Win is loading jne notload cmp CX O this must always be 0 else error jne goerror2F mov cS winmode dl bit 0 0 if Enhanced mode test dl 1 test bit 0 jnz standardload eS a a i rs inserts our vxd into vxd chain see my book Appendix D mov word ptr cs instdata SIS Next Ptr bx mov word ptr cs instdata SIS Next Ptr 2 es push cs pop es chain with es bx ptg to our instdata lea bx InstData structure our VxD data structure a jmp SHORT go2F notload cmp ax 1606h test if Win is unloading jne notunload mov e s winloaded 0 mov cs dpmiloaded 0 jmp SHORT go2F tee onload cmp ax 160Bh used for tsr registration with win
450. s data in the code segment and then called POSTMESSAGE Note that I did not make use of aliasing in this simple skeleton I chose to explicitly push the parameters onto the stack prior to the CALL rather than use the PASCAL qualifier TASM s generation of code with the PASCAL qualifier is horribly inefficient so I felt better about doing it this way Enhanced Mode Hardware Interrupts So what about Windows in Enhanced mode Remember that Windows 95 can only run in Enhanced mode I mentioned earlier that Windows gets up to some tricky business and for both Standard and Enhanced modes reflects the INT 5 1 h to INT 9 However this mechanism is different in each case as Enhanced mode is able to make use of virtual machines with the result that hooking either INT 5 Ih or INT 9 will work in Standard mode but in Enhanced mode only INT 9 will work So the earlier example code that I wrote to hook INT 5 lh for illustration purposes simply needs to be modified to hook INT 9 and it will work in both Standard and Enhanced modes Unfortunately there is is still one complication DOS I keep hoping it will go away but it won t The hardware interrupt handler developed in this chapter will work with any number of Windows applications multitasking but not when a DOS program is running In the former case it doesn t matter if the program containing the ISR is iconized and another WinApp has the active window still all ke
451. s default cursor ax I i ax IDC_ARROW Standard arrow cursor 100 Windows Assembly Language amp Systems Programming cwd push dx push ax call LOADCURSOR mov WORD PTR bp 32 ax mov ax COLOR_BACKGROUND mov WORD PTR bp 30 ax mov ax OFFSET szskeletonname mov WORD PTR bp 28 ax mov WORD PTR bp 26 ds mov WORD PTR bp 24 ax mov WORD PTR bp 22 ds lea ax WORD PTR bp 46 wndclass push ss this is address of above data push ax structure Register Note that we only have to call RegisterClass for the first instance Class of the program If you double click on the program icon a second time the second instance of the program created in memory will not have to register the window with Windows call REGISTERCLASS registers this class of window or ax ax error test je Quitwinmain Displaying The above block of code registered the specifications of our a window program window with Windows Now to display it Parameters that have to be pushed on the stack prior to calling ea CreateWindow are a long pointer to window class name Ip to the window title name type of window x and y coordinates width and height parent handle menu handle instance handle and an Ip to parameters to link with the window createwin mov ax OFFSET szskeletonname push ds long pointer far address of push ax class name mov ax OFFSET szwintitle push ds far address of window title
452. s directly in assembly Why not use your compiler in line assembly capability What you gain is code that does what it was developed for and is efficient compact and highly readable Assembly language code is far more readable than some C code Ive seen In fact what you end up with is code that is more portable than if the whole thing had been done in the high level language The 368 Windows Assembly Language amp Systems Programming The bottom line reason for this is that the boundary between strictly non hardware dependent code and hardware dependent code is clarifed In fact you can bet that some programs written exclusively for Windows NT will have assembly code To transport the program to another platform the developers will simply recode the easily distinguishable hardware dependent portions Binary compatibility is a fascinating aspect of Windows NT This means that assembly language code will work on all hardware platforms The x86 instruction set and hardware dependency will be emulated to the extent that most Windows programs will run without recompiling but it remains to be seen how far we can push this This is another exciting area to research There will always be a demand for assembly language programmers due mostly to competition If word processor A runs twice as fast as word processor B which one has the edge And if word processor A runs in half the memory again the choice is obvious We have not by an
453. s entered with EBX current VM ECX type of I O EDX port number and EAX output data if type of I O is output When the callback exits if the type of I O is input the value placed in EAX is the input value The book should also explain the VMM INC macros and data structures such as the Dispatch Byte 10 macro used above 358 Windows Assembly Language amp Systems Programming The Maximum Productivity Now for something completely different What I would like to do is present you with an idea and an philosophy ofimplementation of the idea Basically the idea is that you should extremes True visual programming do only two extremes of programming very low level or very high level and nothing in between The rationale for this is very simple for programming you want above all else productivity that is the most program for your money Now productivity also includes maintainability because that is part of the cost equation To maximize productivity you want the most powerful programming tools On the other hand if you need to do low level work you should use the tool best suited to the job assembly language rather than try to torture a high level language into performing low level tasks Sure you can use something like C to perform low level work but it is really just a very awkward mimicking of assembly language and is definitely hardware dependent therefore you should r
454. se something else is required the prototype 128 Windows Assembly Language amp Systems Programming TASM You can only use INVOKE to call a procedure that has a PROTO declaration even if the procedure is external as in the case of Windows functions Previously I used EXTRN to declare MESSAGEBOX as external and that is still recognized by MASM but PROTO can be used to replace EXTRN So for each and every Windows EXTRN declaration replace with PROTO as shown and MASM external declaration EXTRN MESSAGEBOX FAR MASM 6 00 prototype for INVOKE MESSAGEBOX PROTO FAR PASCAL HWND LPSTR LPSTR WORD Passing 32 bit values ADDR H to NC convertor You should find the syntax of PROTO to be self explanatory The parameters have to be declared with their types and can have arbitrary or no names You can also get away with declaring all types as WORD 16 bits rather than more specific 16 bit types such as HWND or BOOLEAN Actually its not PROTO itself that replaces EXTRN rather INVOKE defaults to external in line with C s default behaviour Notice how I passed the FAR address long pointer in TASM compared with ML In the PROTO declaration above you can see the data type HWND which is 16 bits but LPSTR is a 32 bit value Long Pointer to STRing With TASM I passed the segment offset as two separate items though it is possible to declare a 32 bit pointer but this will cause an ass
455. sed portions of DOS on the disk bringing them in as needed CPU Architecture 5 CONFIG SYS System files have an extension of SYS and may be programs or FILES BUFFERS DEVICE DEVICE COUNTRY Real mode text files I have already mentioned above that MSDOS SYS is a code file in early versions of DOS and a text file in Windows 95 systems A major group of SYS files are what is known as device drivers these are programs that load and become semi permanently resident in memory CONFIG SYS is a system text file that is automatically read from disk during the PC s startup procedure CONFIG SYS can be created by any text editor and consists of a number of commands Here is an example of a CONFIG SYS file 40 40 ANSI SYS GMOUSE SYS 21 061 Refer to your DOS User s Manual for more details An important device drivers point to note here is that DEVICE is a command that allows you AUTOEXEC BAT to load more device drivers into the system GMOUSE SYS for example is driver software for a mouse and loading this driver will allow any program that can utilise a mouse to do so But note that this will be what is called a Real mode driver designed to work with DOS Windows applications can use Real mode drivers but there is a performance penalty Therefore Windows has its own drivers that are not specified in CONFIG SYS instead they are specified in another file SYSTEM INI located in C WINDOWS SYSTEM director
456. sed to detect that no slash was in the string Because the string instruction automatically increments DI each time at termination DI will point to the next character past the last one tested If the slash was found this next character will be the switch Note that Windows 3 x and 95 applications still have a PSP The value in the location pointed to by DS SI is loaded into AL or AX SI is automatically incremented 1 if LODSB or 2 if LODSW The value in AL or AX is stored at the location pointed to by ES DI DI is automatically incremented 1 if STOSB or 2 if STOSW STOS and LODS are most useful for video access as the format of video RAM in text mode requires every odd byte to be an attribute character Setup ES DI Setup DS SI mov cx string_length mov ah attribute next char lodsb stosw char gt AL AX gt destination loop next char this code will send characters to the screen Arithmetic Instructions PREREQUISITES These include addition subtraction multiplication and division I expect you to have a working knowledge of the principles of binary arithmetic unsigned binary numbers 2 s complement binary numbers radix conversion among hex binary decimal For example suppose I ask you to express 2 as a 32 bit binary number and also as a 32 bit hexadecimal number Can you do it If the answer is yes then you do have a few clues so read on Otherwise look back at
457. selector 8025h invalid linear address descriptor references a linear DPMI Services 391 address range outside that allowed for DPMI clients Int 31h Function OOODh Allocate specific LDT Descriptor Allocates a specific LDT descriptor Call with AX OOODh BX selector Returns if function successful CF clear and descriptor has been allocated if function unsuccessful set AX error code 8011 h descriptor unavailable descriptor is in use 8012h invalid selector references GDT or beyond the LDT limit Int 31h Function OIOOh Allocate DOS Memory Block Allocates a block of memory from the DOS memory pool i e memory below the 1 MB boundary that is controlled by DOS Such memory blocks are typically used to exchange data with Real mode programs TSRs or device drivers The function returns both the Real mode segement base address of the block and one or more descriptors that can be used by Protected mode applications to access the block Call with AX 0100h BX number of 16 byte paragraphs desired Returns if function successful CF clear AX Real mode segment base address of allocated block DX selector for allocated block if function unsuccessul F set AX error code 0007h memory control blocks damaged also returned by DPMI 0 9 hosts 0008h insufficient memory also returned by DPMI 0 9 hosts BX size of largest available block in paragraphs 392 Windows Assembly Language
458. shadow register to find out the starting address of the segment plus some other information and can then go ahead and put together the full 32 bit address for fetching the instruction The CPU will add the base address to the offset IP and get a 32 bit address that can be put onto the address bus Descriptors I have introduced the descriptor as being an entry in the GDT or LDT There are various types of descriptors but the most common is the normal addressing type that we have been discussing so far Each descriptor is 8 bytes in size and Figure 1 13 shows what a normal descriptor looks like Figure 1 13 Descriptor format access base 7 Size of Normally set Base is the address to zero on the of the segment 286 Base extends the base segment addressing beyond 24 bits extends the limit beyond 64K segment Access field The access byte in Figure 1 13 has various flags and codes It has a two bit DPL field Descriptor Privilege Level that determines the privilege level of the segment It has P Present and A Accessed bits that are used for moving the segments in and out of memory There are R Read and W Write bits that set constraints on reading and writing the segment There is also the C Conforming bit and ED The latter is set if the segment is a stack I go into the description of the descriptor in far greater detail in Chapter 12 386 Paging There are two paging modes in t
459. sname mov di ax mov di 2 ds lea ax sl invoke REGISTERCLASS ss ax or ax ax jne createwin jmp guitwinmain createwin invoke CREATEWINDOW ADDR szASMDEMOname ADDR szwintitle Q0CFO000h 150 O 400 300 0 O hInstance 0 mov hWnd ax invoke SHOWWINDOW ax nCmdShow invoke UPDATEWINDOW hWnd jmp SHORT messageloop go to the main message loop This is the main message loop in which Windows waits for messages mainloop lea ax s2 invoke TRANSLATEMESSAGE s8 ax lea ax s2 invoke DISPATCHMESSAGE s88 ax messageloop lea ax s2 invoke GETMESSAGE ss ax null null null or ax ax jne mainloop GetMessage returns FALSE AX 0 if a quit message 780 here we are gquiting mov ax S2 WPARAM return wparam to windows OS quitwinmain PSE 134 Windows Assembly Language amp Systems Programming WINMA INENDP ASMDEMOPROC PROTO FAR PASCAL HWND WORD SWORD SDWORD ASMDEMOPROC PROC FAR PASCAL ihWnd HWND iMessage WORD iwParam SWORD ilParam SDWORD LOCAL dummy 5 WORD LOCAL hDC HDC LOCAL s3 PAINTSTRUCT mov ax imessage get message type cmp ax WM CREATE message received after CreateWindow je xcreate function is called cmp ax WM_DESTROY message received if a window is closed jexquitmessage cmp ax WM_PAINT j message received if Windows has already redrawn any part of the window due to a Size change for example je xpaint cmp axX WM_COMMAND any selection of
460. so I will weave my way back to the next step Processing the CREATE message Processing the PAINT message Processing the COMMAND message Program Design 157 Kickstart kickstart is where the ball starts rolling Of course the entry point to your program is at WinMain Q but this function is inside WINASMOO INC WinMain takes care of all the red tape and ends up calling kickstart kickstart must always be in your object oriented program Again Ive left off the PROC PASCAL ENDP for the sake of brevity and simplicity A static instance of the WINDOW structure already exists in the data segment so the first thing that kickstart does is get the objects address The next thing it does is actually create the window and display it on the screen You will remember from previous chapters that this was a particularly long winded process Look back to page 116 and you will see that the application calls Windows CREATEWINDOW function to create the window then SHOWWINDOW and UPDATEWINDOW to actually show it on the screen All of this is red tape and is hidden away Message Handling After creating the window Windows sends a WM_CREATE message to the window callback function I used this message to get the handle to a particular font that I used in the program yes even fonts have handles Hence I put in the wlcreate routine Whenever Windows redraws any portion of the client area of the wind
461. sponse to IDM ABOUT to call RINGOCALLGATE which is a pointer to the call gate which takes execution to the ring 0 code Finally before exiting from the program it calls freeourselectors which removes the descriptor and call gate that we had created in the LDT Now for the part that does the real work DATA dpmiproc DD O dpmi extensions entry point RINGOCALLGATE LABEL DWORD use this to call ring O code ringO_off DW 0 callgate selector for RINGOFUNC ring0_cs DW Q offset is ignored ms_dos str DB MS DOS 0 ldt_ selector DW 0 for direct writing to ldt descriptor_selector DW 0 ring0 cannot be accessed directly ringOerrormsg DB Error creating ring 0 access aborting program 0 CODE makering0Oselector PROC invoke GLOBALPAGELOCK cs cm ax 0 je lockfailed find out where the LDT is lea si ms dos str mov ax 168Ah get dpmi extensions entry point int 2a gt pes di undocumented jee cmp al 0 Lae ee peer ne extensionsnotfnd mov WORD PTR dpmiproc di save entry point mov WORD PTR dpmiproc 2 es mov ax 100h undocumented call dpmiproc gt ax selector to ldt jc extensionsnotfnd mov lIdt_selector ax mov es ax create a ring 0 32 bit descriptor push es invoke ALLOCSELECTOR cs gt ax alias to cs pop es cmp ax O je selectorerror and ax OFFF8h get offset of descriptor in ldt mov bx ax 32 Bit Ring 0 297 mov al es bx 5 get access rights byte and al 100111
462. ss The instances are objects A structure is just a convenient way of getting at data In this case we have data labels fieldl field2 and field3 By putting the STRUC and ENDS directives around them we have a convenient mechanism for creating mutiple copies of those same data declarations The declarations between STRUC and ENDS don t actually get assembled it is a template and wherever we create instances they are what actually assembles In this case there are two instances winl and win2 These are identical blocks of data able to have their own values but with identical variable field names In OOP we would call each field a member The example code shows how we can get at these two instances The most common method would be the first example If I had want to access the field2 field of win2 the instruction would simply be mov ax win2 field2 You can have as many instances as you wish and as you will see in Chapter 5 structures can be automatic or local to a procedure Label Equates It is extremely useful to understand how the assembler assembles structures Normally the assembler equates data labels to their offset from the start of the data segment but fields of a structure are equated to offsets relative to the start of the structure In the example field1 equates to O and field2 equates to 10 When the instances are created the names winl and win2 are treated as normal data labels and thus are equated
463. ssage to the callback function your callback processes it then has nothing more to do so returns to Windows If control stays in the callback for There are two other services AX 4005h and 4006h that are similar to 4000h and 4001h respectively The description of 4005h is The Windows VDD calls this function to tell the display driver to save the video hardware state And for 4006h The Windows VDD calls this function to tell the display driver to restore the video hardware state that was saved by the last call to function 4005h Writing Windows Device Drivers page 78 The 4000h and 4007h services are used in conjunction with 4005h and 4006h 4000h gives the display driver direct access to the video hardware registers while 4007h disables register access and tells the VDD that the display driver has finished accessing the video hardware Though the DPMI host does perform preemptive time slicing between VMs see Chapter 11 Even this can be disabled by a DPMI service Direct Hardware Access 231 whatever reason then no more messages are sent to it therefore your callback is not receiving anything from Windows At least not in the normal way just register that as an interesting point for now Restore Video For now Il just say that you can save the screen upon entry to the callback and you can write directly to the screen But before going back to Windows you must restore things to how they were This means that w
464. ssed two parameters arbitrarily named parl and par2 At the end I passed the address of the object that is to be acted upon Further down in the actual code for textoutmain see how I used a variable THIS to receive that address This is important we must always pass the address of the object to the function Late Binding The second call in the above listing page 140 is an example of late binding The meaning of this is call the TEXTOUT function in the instance windowl Another way of writing it is call OFFSET_windowl TEXTOUT This is non immediate and will call the function pointed to at offset_window TEXTOUT which in this case is textoutmain The end result is the same as for early binding except that this one call instruction will call whatever TEXTOUT function we want simply by setting SI appropriately beforehand lea si window2 call window2 TEXTOUT PASCAL parl par2 si call si TEXTOUT PASCAL pari1 par2 si This code calls textoutdlg The last two lines are actually the same due to the way in which the assembler treats the window2 label in this context but I recommend that you stick with the latter to avoid confusion THIS passed on the stack must always be the register not the label so be consistent and use SI in both places This implements polymorphism C Binding Examine this C code class WINDOW ye ene here does exactly the same as the assembly language on page 140 public
465. ssins Data serro iste k eriy a ra E aKO EEEa POiNTETS de ent ertek hose he oee Si oeae Sou wee k LES LDS and LEA Instructions s esesessssesserers Local Data srira rretan ered E A E E Type Override srerrisr inio oe Ea EAEE SUMICKUIES ieie E EE EE E ENA nek EAT Label Equates ecrit t naana a A aa Postamble gaere soe EAA RAE TE E ese aes Opening Windows Preamble suai raau TETEA DOS versus Windows Programming sssreseserrerrsee Internal Differences rsersresererereererrerrer Building a Windows Application sssssesesrerrerersssi Library Functions 0csccceseteevscacbencearecees The Mechanics of Assembling and Linking The Link St piwevesiassess teen eausto aso tretoe see seks Two Steps for Resources 1 eee cece eee eee e eens Windows Programming Mechanics seeeeeseeene eens ODJECIS asrese ase bra ree nhaw wer Seve EINE EEA Handles fisicde cece acces tues senate Ea et INSTANCES occ doen IAEA RNAS eater eee RAS e eet bask MESSAGES s sessosoresrevoeoseposoosorecosoesnrseses C Synta a eea a voeeiee ts Sea a a E p a Message Loop essesersssssseresesereoerseserseeee Callback Functions s sssessssreseserssreesrerese Data Types aro masnir Onean ianu NEART E asia Ch Page 4 The Bare Bones 85 Preamble rinas in ee aT anced hina wieces vera tees 85 Getine Started ys paca irra ia Creer AEE A EEN Ra 86 IROOISW REQUIRE eese eea inn oE EA A Ea ais 86 SOURCE Files ower ssssroisesenseioru
466. st as easily be defined in the code segment amongst the code or in the stack Chapter 4 explores the use of the stack for holding data Segment override is introduced on page 46 DB DB Define Byte DW Define Word and DD Define DW Doubleword define 8 16 and 32 bit data respectively For DD example var2 is a 32 bit value of 0 ary1i shows the use of the DUP DUPlicate directive which causes the assembler to assemble 64 byte size values initialized to 0 Now for the key points the assembler equates a data label to its address just as for code labels However depending on the instruction it assembles a non immediate i e direct see page 45 addressing mode into the instruction operation code op code This difference is vital mov AX varl referencing a data label mov AX placel referencing a code label Major The above examples show the difference At execution time the distinction second MOV instruction will move the actual address of placel between code into AX while the other MOV instruction will use a and data non immediate mode moving not the address varl but its content labels Thus although MOV AX var1 assembled with the address of varl as the operand to the instruction at execution time the instruction looks at the content of that address Make sure you have grasped this distinction before continuing Accessing Data Sometimes when writing a program you want to know the address of something say a
467. st one LDT and all the 16 bit WinApps have one set of pages tables Each 32 bit WinApp has its own set of page tables Therefore each 32 bit WinApp can be mapped to physical memory totally independently of any other application They sit in linear address range 2G to 4G but of course big chunks of the linear address range map back to the same physical memory as other WinApps DOSApps and Windows The best places to look for extreme detail on this mapping is Unauthorized Windows 95 by Andrew Schulman IDG Books USA 1994 and Windows 95 Systems Programming Secrets by Matt Pietrek IDG Books 1995 DPMI allows us to obtain a selector for a particular linear address see functions 0000h and 0007h but what use is that to us if we dont know what the linear address represents One extremely interesting aspect of Windows 3 x mapping of the 4 3G virtual space is the linear address starting from 0040 0000 This range maps directly to physical memory Again I cannot guarantee this for all versions of Windows Thus if you wanted to access the physical video buffer at segment offset A000 0000 you would convert it to a full 32 bit linear address OOOA 0000 and add it to 0040 0000 That is 0040 0000 maps directly to physical address 0 and 004A 0000 maps to the physical video RAM Chapter 12 shows that the VxDs use 32 bit ring 0 selectors 28h and 30h that are in the GDT These are FLAT selectors having a base address in the descriptors of zero
468. stion regarding the dual purposes of the bus 184 Windows Assembly Language amp Systems Programming ProgrammableMore special chips are used for the interface between the buses Peripheral Interface OUT 5 AL Hardware description and the external world By external I also mean the keyboard disk drive etc Notice that the I O chip in Figure 7 4 is labelled PPI This is the name given to a chip used in early model PCs PPI means Programmable Peripheral Interface and it is a simple general purpose I O chip with three external 8 bit ports as shown The functionality of the original PPI is still in the latest PCs it is just contained within a larger chip We refer to big chips as VLSI technology Very Large Scale Integration Notice that the PPI in Figure 7 4 has only two address lines going directly to it That is because it only has four ports or registers Three of them are ports A B and C and the fourth is a configuration port I O Instructions Although the address bus is used to select I O ports only AO to Al5 are used so the address range is only 64K With the I O instructions data is always via the AX register The I O port address must be placed in DX before executing the I O instruction if the address is over 256 Examples A byte from port address 2Fh loaded into AL jpawaqQrur a word from 2Fh to AX Contents of AL written to port 5 Keyboard Interface This section talks a little bit about
469. sue of Real mode Windows 3 1 won t run in Real mode only Standard or Enhanced version 3 0 loads in any of the three while 95 only loads in Enhanced mode Real mode in this context means that the WinApps themselves run in Real mode which just isn t practical So we load Windows in Standard or Enhanced mode why bother with Real mode One need is to run a DOSApp In the case of Standard mode the CPU has to switch back to Real mode effectively freezing Windows However Enhanced mode will create another VM virtual machine in which to run the DOSApp and we still say that the DOSApp is running in Real mode though it would be more correct to say virtual 86 mode Then there are DOS device drivers and TSRs Most likely these will be running in Real mode And there are the BIOS and DOS services that we may still want to use A lot of code is still being developed to run in a DOS box maybe in Protected mode but still involving transitions between virtual 86 Real mode and Protected mode in the DOS VM 267 268 Windows Assembly Language amp Systems Programming A typical problem with porting code from DOS to Windows Interrupts reflected from IDT to IVT Code in Protected and Real mode must be able to communicate and interrupts occurring in both modes must be handled correctly The former is the major topic of this chapter with hardware interrupts focused on in Chapter 12 This chapter is split in
470. sult up to 32 bits long Thus in the case of CPUs with only 16 bit registers the result may have to reside in two registers The MUL instruction uses AL and AX or AX and DX by default al bl gt ax ax bx gt dk hax 54 Windows Assembly Language amp Systems Programming div bl div bx AN TEST The first example makes the assumption that the other operand is in AL so the result will appear in AX The second example makes the assumption that the other operand is in AX and the result will be in DX AX Division has problems of its own The dividend the operand to be divided is in either AX or DX AX and the divisor is in any other register or variable 8 or 16 bits ax bl gt ah and al gt dx ax bx gt dx and ax The first example assumes the dividend to be in AX and puts the result in AX in this format AH remainder left over AL quotient result The second example specifies a 16 bit divisor which assumes that the dividend is in DX AX and the result in DX AX as follows DX remainder AX quotient A feature built into the CPU is that if there is an error in the calculation a certain interrupt is generated and DOS displays an appropriate error message In the case of DIV it is possible for the quotient to be too big for AL or AX DOS will abort your program with a division overflow message Logical Instructions Logical instructions basically work on individual bits rather than c
471. sverecee cic ey cheesy E TEE oe awe aed 178 PC Hardware 179 Preamble ose vides kuria tenunan TE ge eaters dene 179 CPU DU 2st ica a T A ciao EUA ETENE tec 179 Control BUS wa xiianeien aE EEE E E eae 180 Address Decoder s seresesesessesseseerosercerens 182 VO POTIS 6 EE 5655 A REEE A EERE A A EEA A REE a 183 VO INStruChOns ceait a E E OEA 184 Keyboard Interface ssesrerseroseerererrrerrereesr 184 AT Class Keyboard Port Enhancements 186 PC Expansion Buses eeeeseeeee eee e cece ener ener cecees 187 Industry Standard Architecture ISA e eeee 188 Peripheral Connect Interface PCI eseeeeeeeeereeees 19 1 Postamble asiewvasecs eet enn cee eter anedse eevew exceed ewes 194 BIOS DOS amp Windows Low Level Services 195 Preamble oessssessreeroreroresoneessererrerrerreree gt 195 BIOS and DOS Services cc cece eee n erence ence ee eees 197 Standard DOS Interrupts s esererersrresereresere 200 DOS Protected Mode Interface DPMI e ess 203 INT 2Fh Extensions esssrereresresreereerererereres 205 Ch 9 10 11 vii Page Windows Functions 6 isiesk cose aoe eae tae ha cued ee ce Oeaiee en 207 TRUNKING indsains esp denegeneewseccairate aa anv er sae eee es 219 Generne Thinking soy iwi Rates eerie 219 More Win95 Improvements esseeeee eee cere eens 222 Device VO Control seeriana T a EA 222 Dynamically Loadable Drivers 293 Threads cx tas to
472. t WinApps System level access in Windows 95 Structure of this chapter Sometimes I feel quite disgusted with Miscrosoft because the playing field keeps changing For example Windows 3 0 had WinApps and the API DLLs running at ring 1 while DOSApps ran down at ring 3 Then in Windows 3 1 everything went down to ring 3 including the DLLs Windows 95 also has everything at ring 3 except of course the insides of Windows such as much of the VMM Virtual Machine Manager and the VxDs virtual device drivers Actually 16 bit Windows applications should not be viewed as inferior as it may turn out that they will give better performance than equivalent 32 bit applications As explained in Chapter 12 all that is meant by 32 bit is that instructions in a 32 bit segment default to address and size of 32 bits and they no longer have the 64K segment size limitation Sixteen bit WinApps actually have some advantages when it comes to global addressing and general messing around inside Windows and with the hardware Microsoft has tried to close the door to low level access for 32 bit WinApps so there is no direct access to the interrupts or the low level API functions All the low level facilities are still there however and will continue to be there it is a matter of knowing how to get at them Sixteen bit WinApps running in Windows 95 have easy access to them for backwards compatibility reasons Most of the deve
473. t this gt dosomething 0 call si WINDOW dosomething qv Co si late binding no other params to pass r getting at data member of current object X active mov ax si 0 offset is 0 since field is first in mov xX ax object ret B WINDOW TEXTOUT qii ENDP END The skeleton program gives you the mangled names and how to access the dataandfunctionmembers Thenyoucango ahead and flesh outthe assembly module Your next step would be to remove the stub from the C module and compile as follows BCC filenamel CPP filename2 ASM Or if the fancy takes you it can be done in steps BCC c filenamel CPP TASM ml filename2 ASM file TLINK filenamel filename2 Note that Borland C does have a mechanism to suppress name mangling for linking with Standard C modules but I found it too limited for assembly work It doesnt work for data and function members Coding development over previous chapters A 9 line skeleton Program Design 153 Note also that C does have an EXTERN declaration so that any function that is referenced in the C module but is defined in the assembly module can be declared as EXTERN However this also has limitations and is optional anyway The Amazing 9 Line Program So you think assembly language programming for Windows is difficult think again The high level assembly language program of Chapter 5 is not much longer than one written in C or any other conventional
474. t 2Fh Functions 4001h and 4002h DATA STRUCTURES Win386_Startup_Info_Struc Win386 Startup_Info_Struc STRUC SIS_Version db 3 0 SIS Next Dev Ptr dd SIS_Virt_bev _File_Ptr dd a SIS_Reference Data dd SIS_Instance_Data_Ptr dd a SIS_Opt_Instance_Data_Ptr dd 0 Win386_Startup_Info Struc ENDS The Win386 Startup Info Struc structure contains information that Windows uses to prepare an MS DOS device driver or TSR program for operation with Windows Member Description SIS Version Specifies the version number of the structure 386 Enhanced mode Windows uses this member to determine the size of the structure This member should contain 3 in the low order byte and 10 in the high order byte to indicate that it is version 3 1 SIS Next Dev Ptr Points to the next structure in thelist The address of the next structure must be supplied by the next handler in the INT 2F Extensions 41 I Interrupt 2Fh chain A driver or TSR calls the next handler then sets this member to the address returned by the handler in the ES BX register pair SIS_Virt_Dev_File_ Ptr Points to a null terminated string that contains the name of a 386 Enhanced mode Windows virtual device file MS DOS devices such as networks use this to force a special 386 Enhanced mode Windows virtual device to be loaded If this member is zero no device is loaded SIS_Reference Data Specifies reference data for the virtual device This member used only when SIS Virt_Dev Fil
475. t Binary American signed magnitude number decimal for Information number Straight binary Z s complement Standard Code Mstruction operation code Interchange ASCII binary coded Considering each of the above 00110100 could be treated as a magnitude only straight binary number or the most significant bit MSB could be a sign leaving 7 bits for the magnitude this is not the same as 2 s complement Considering it as a straight binary number 00110100 0 2 0 2 1 25 1 24 0 2 1 2 0 2 0 2 2 decimal That is 52 decimal is represented in memory by 00110100 binary Positive numbers in 2 s complement look just like unsigned straight binary numbers They are distinguished as ve by the MSB i e the left most bit being 0 A 2 s complement negative number is distinguished by the MSB being 1 8 Windows Assembly Language amp Systems Programming Binary coded decimal BCD ASCII Instruction code Base or radix Hexadecimal The value 00110100 is 52 decimal so how does 52 look The rule is invert all bits to the left of the first bit from the right set to 1 Thus 11001100 BCD is another way of storing decimal values in the computer The bits are grouped into lots of four each group converted to decimal 0011 and 0100 become 3 and 4 That is 34 decimal is represented in memory by 00110100 The code does not represent a number at all but a character From
476. t Corporation All rights reserved Reprinted with permission from Microsoft Corporation
477. t addressing mode DIRECTEDYIELDQ Direct memory access Direct video Direct video text mode Direction flag DF DISABLEOEMLAYER DISPATCHMESSAGE DIV instruction DLL DLL assembly language 138 213 213 31 245 75 126 129 44 51 49 56 289 4 216 2 49 147 4 13 180 172 14 12 24 179 22 12 217 247 215 100 208 232 236 41 208 208 52 80 208 89 80 26 28 289 104 92 DMA DOS amp BIOS services DOS stub DOS vs WINDOWS programming DOS3CALL Dot operator DPMI 0 9 and 1 O DPMI is it available DPMI overview DPMI services when to use DPMI which version is running DUP directive DW Define Word DWORD 32 bit Dynamic Link Libraries DLL s Dynamically loadable drivers E Early binding EFLAGS register EIP ENABLEHARDWAREINPUT ENABLEOEMLAYER ENABLEWINDOW Encapsulation of data within an object Epilog code EQU Equates Event driven Event driven program structure Exception handling conflict Exception handler EXEHDR EXE Expansion bus Extended amp conventional memory EXTRN F FAR CALL FATALEXIT Fixing segments in place FLAGS register FLAT memory FLAT pointer FREELIBRARY FreeLibrary32W FREESELECTOR Function member calling G GDI functions GDT GETASYNCKEYSTATE GETCURRENTPDB GETCURRENTTIME GETDOSENVIRONMENT GETFREESYSTEMRESOURC ESQ GETINPUTSTATE GETINSTANCEDATAQ 209 209 238 209 146 106 130
478. t does the dirty work PASCAL There another important aspect to the above high level PROC epilog the PASCAL qualifier This eliminates the need to explicitly code prolog the prolog and epilog code Again look back at page 98 The standard prolog code which is not part of the program listing is push bp save old bp value mov bp Ssp set bp pointing to return address sub sp 46 operand varies see notes below The standard epilog code whichis not part ofprogramlisting is mov sp bp set sp pointing to return address pop bp restore old bp value ret 10 operand depends on of parameters to dump Now back to the program listing Define all automatic data LOCAL hWnd WORD window class structure for REGISTERCLASS LOCAL s1 WNDCLASS message structure for GETMESSAGE LOCAL s2 MSGSTRUCT LOCAL The original prolog code contained sub sp 46 to move the directive stack further down in the stack segment allowing a free area in which to store local data Once again we can eliminate the need to explicitly code this Declare all local data using the LOCAL directive with a syntax as shown above Incidentally the default type is WORD so if the data is of type WORD you dont have to declare it Note that you cannot initialise this data since it is only created at execution entry to the procedure not at assemble time For an introduction to local data refer back to page 62 114 Windows Ass
479. t from INT 10h You could try the C run time library or DEATH RESURRECTION The latter although undocumented is probably the best supported and cleanest method Overwriting the current Windows screen Virtual vs physical video RAM Suppressing redrawing Direct Hardware Access 237 Notice from the above listing that used INT 10h AH OFh to obtain the current video mode before changing to mode 7 After doing my thing I used INT 1 Oh AL 00 to change the mode back to what it was Mode 7 is the original text mode for the MDA card giving monochrome 80 columns by 25 rows It works on EGA and VGA adaptors but not on CGA The reason for this is that CGA does not have high enough resolution CGA text mode is mode 2 or 3 and is only 640 x 200 pixels while mode 7 is 720 x 350 pixels The old mono MDA screen gives a nice sharp image This problem is a point in favour of DEATHO Video Output Issues You do not necessarily have to change the video mode A typical application might be to leave the Windows screen as is and overwrite it Think about this there are Windows functions to obtain coordinates of your application window or you could call functions to set your window to certain coordinates Then you will know exactly where it is so when you go into direct video access mode you will be able to write to the portion of the screen that is within your window This means that you can have your program running as a wind
480. t that works with Make files in its native mode though the Make files are highly stylised PWB can however read ordinary Make tiles and you can open a project by opening many of the Make files given in this book You can figure out what the above Make file does it assembles SKELETON ASM using MASM EXE then it compiles SKELETON RC using RC EXE then LINK EXE links everything together and finally RC EXE is executed again to combine SKELETON EXE and SKELETON RES the compiled output from the first RC execution to produce the final SKELETON EXE Development Cycle You can run the Make file from the DOS prompt but you can also do it from within Windows What you should do is open the File Manager and go to the directory containing the application Then iconize the File Manager and open the Notepad Use the Notepad to view and edit SKELETON ASM and iconize when finished It is a simple matter to flip between the Notepad and the File Manager When in the File Manager and the directory containing the application is open and the directory must contain all software tools if the SDK is not installed properly on the PC select Run from the File menu In the box type NMAKE SKELETON MAK just as you would on the DOS command line After running the Make file all you need to do to test your program is double click on SKELETON EXE in the File Manager Other ways The Bare Bones 93 The above is not the only way t
481. t together The DMA controller is given the selector offset and simply increments the offset without regard to paging remember that the CPU is turned off at this time and the DMA chip has complete control of the bus Another implication of this is that it is wise to keep memory buffers to no more than 64K I did note earlier that by declaring the DLL data segment FIXED it will load below 1M and be contiguous However there appears to be some doubt about the latter as the recommendation is that to ensure that pages are contiguous another service must be called the INT 4Bh Lock DMA function INT 4Bh provides the extensions to DOS for DMA handling and you will find these documented in the above Microsoft reference not anywhere else that I m aware of The services available from both Windows Standard and Enhanced modes are e INT 4Bh AX 8103h VDS_LOCK e INT 4Bh AX 8104h VDS_UNLOCK INT 4Bh AX 810Bh VDS_ENABLE_TRANSLAT e INT 4Bh AX 810Ch VDS_DISABLE_TRANSL Some of the discussion in this and earlier chapters has referred to Real mode Although Windows normally runs in Protected mode Real mode is still encountered as is virtual 86 mode and more specific treatment is provided on this topic in the next chapter 11 Real Mode Access Why bother with Real mode Preamble The topic of Real mode has already been encountered at various earlier stages in the book There is however a lot more to the is
482. t using the Set Debug Watchpoint nction Int 3 1 h Function OBOOh Call with AX 0B02h BX watchpoint handle 400 Windows Assembly Language amp Systems Programming FORMAT Heading Description Call with Returns Returns if function successful CF clear AX watchpoint status Bit Significance 0 0O watchpoint has not been encountered l watchpoint has been encountered l 15 reserved if function unsuccessful CF set AX error code 8023h invalid handle Int 31h Function 0B03h Reset Debug Watchpoint Resets the state of a previously defined debug watchpoint i e a subsequent call to Int 3 1h Function 0B02h will indicate that the debug watchpoint has not been encountered Call with AX OQB03h BX watchpoint handle Returns if function successful CF clear if function unsuccessful CF set AX error code 8023h invalid handle INT 2F Extensions These extensions to INT 2Fh are provided by Windows Two others functions 1686h and 1687h are part of the DPMI and are described in Appendix C The source of this reference information is Microsoft s Device Development Kit and more material is to be found there with many example programs Function 1600h 1602h 1605h 1606h 1607h 1608h 1 609h 1 680h 1 681h 1 682h 1 683h 1 l Description Get Enhanced Mode Windows Installed State Get Enhanced Mode Windows Entry Point Address Windows Initialization Notificat
483. t you use the WM_CHAR message as a convenient means of invoking the service routine Having modified another program start both it and the TSR program With the other program active try key presses at least ten and you should be able to toggle the tone on and off 256 Windows Assembly Language amp Systems Programming Only one LDT and IDT IRQ O 7 What you are doing here is accessing a global variable Other applications can also access that same variable which raises interesting possibilities for inter process communication If you know much about LDTs and GDTs you might be puzzled as to how the above code can work The classical theory states that each application has its own LDT see Chapter 1 so modifying the TSR s LDT has nothing to do with any other application s LDT Not so with Windows As is explained in more detail in the next chapter all WinApps share the same LDT Ditto for the IDT The IDT is a very grey area It is another case of Microsoft hiding the truth The classical model for the IDT would be that there is only one but Windows does maintain copies as far as I know for each VM So maybe there is just one main IDT that interrupts go to but the interrupt handler references the copy in the current VM This is a very very grey area but you can get by with just thinking that there is only one IDT Certainly as all WinApps are in the same VM this assumption is safe Hardware I
484. ta it can also have pointers as fields in the structure or a pointer to another structure of pointers and this is one of the key features of the 00 technique Calling a Function With C there are objects and a procedure or function now called a function member or method is part of aclass The objects are instances of a class Data is also part of the class An instance is a complete copy of the class with possible unique initialisations created in memory CALLing a function member method call Object pointer 32 bit coding Program Design 139 For now we will focus on just one implication of this how functions are called After all thats something we want to do all the time while writing a program A simple CALL instruction is what we are familiar with and of course as you saw in Chapter 5 there are high level qualifiers for calling Pascal or C procedures functions and for passing parameters This simplifies the stack manipulation but now with procedures that are part of a class we have something more to consider Say that you have a procedure in a program and for argument sake give it a name TEXTOUT Also say that it uses the Pascal stack handling convention for no other reason than consistency since the external windows functions do Our problem is that we want to call this function from somewhere else in the program No problem you think just do this TEXTOUT PASCAL paraml1 param2
485. ta dens EEEE tata EAEG 23 Real and Protected Modes ssseeeeeeeeeeeeeeee 25 Memory Management sees reire eini a EE 25 Segmentation Only s eseresesssoroereeseeseserses 25 Shadow Registers ccs4uddsannae sean aE Ea amp 26 DESC POES garanie EERI A RR 28 386 Pagine oicisewnensienagueteavetsrsseermceetoees 28 Virtual SG i eet ee aae T ENEE EE NS 29 Contention Issues s sesssessrsrrersoseeeseseerreereo 31 PRIVINE nt se iee E E ETENE 31 VO Privilege g Sica pnd heen ae ER n O i 31 Task Switching ssrssessiecinit edison i anino aN 32 Interr pts acGusiviadwcceassnre reese tens ents enna R 33 Real Mod Interrupts sirs reriro tp tiknan aan aE 33 Protected Mode Interrupts ssssreresessrrrrrrens 34 Postamble sand ssicwcsnaeisaciarwetir ee Siey staan nies 36 Ch 2 Basic Assembly Language Preamble te Nei eek ni in naa epee Ot de E Stack Instructions emeni h Bae G nae eee eee Transfert of Control 2o 2svb sevens fade i anaia aewersie tags Conditional Jump s sesssssssesesosesereeeesseres Addressing Modes s ccsedcerectnscesevetenserdeearenees Segment Registers scecesceeseceeerereereeees String Instructions ccecece cess erate eee t ene eenees Arithmetic Instructions ss cis sas ciee cade ake SRS ae ses Logical Instructions ccseeerene eet e tere e nee n ences Code and Data Labels s esssesesreresrsrsesrereereraso Code Lab ls ereis mereerin iii aE E et vets eer Data Labels iien dere nEaN ACCe
486. tart of stack segment bucket If there is nothing in the bucket SP Higher addresses FFFFEh or whatever the stack size this way is FFFFEh is correct for COM tiles SP top of Now put a couple of values in stack stack grows down This is the program oeo PUSH CX PUSH AX POP BX The stack always treats values as 16 bits word so each entry actually occupies two memory locations not shown here Note that the last instruction popped the top off value from CX ii the stack into BX The stack is a temporary storage area whose actual address we don t need to know It does have a limitation when SP O the stack is full Transfer of Control The idea of a computer program is that it is a sequence of instructions in this book we are looking at machine instructions that the CPU directly understands Assembly language is just a symbolic more meaningful way of writing the machine instructions 40 Windows Assembly Language amp Systems Programming LOOP J MP CALL INT JX The CPU executes the instructions sequentially that is one after the other in order of increasing addresses but can also jump out of sequence The topic of this section is those instructions that cause execution to go to some other place in the program The main ones are LOOP JMP CALL INT and Jx In this section we will examine CALL JMP and Jx LOOP and INT are examined a little bit later Figure 2 2 Stack ha
487. tart up code of the video ROM executes it changes the contents of entry 10h in the IVT to point to its own video ISR contained in its own ROM Note also that a little later the start up sequence scans the address range C8000h to F4000h looking for more ROMs which will also be executed Incidentally valid code is identified by 55AAh at the first two memory locations with offset 2 holding the size of the ROM module expressed in 5 12 byte blocks Execution will commence at offset 3 of the ROM In the case of video there is a very practical outcome of the above mechanism when writing a program use INT 10h to access the video 1 e to send characters to the screen etc and you know that it will work regardless of what video adaptor card you have plugged in The original INT 10h ISR in BIOS ROM is fairly basic and may not work properly with your video adaptor card especially if the PC is old The redirection of INT 10h to a new ISR avoids the problem of obsolesence It is interesting to note that all of the above is done by the BIOS start up code before the system disk is accessed Later the bootstrap program from the Boot Record on the system disk is loaded followed by IO SYS and MSDOS SYS in the case of loading the DOS operating system When IO SYS is loaded and executed it sets up interrupt vectors 20h to 3Fh in the IVT BIOS ROM or the extensions provides services with addresses in the IVT So does DOS and the DOS services
488. tate Interrupt 2Fh Functions 4005h and 4006h if it needs to access the video registers The VM application must provide an appropriate interrupt handler to process these functions When an VM application calls this function the VDD saves the current state of the video registers The VDD uses this saved state later to restore video registers before it calls Notify Foreground Switch and Restore Video Register State Interrupt 2Fh Functions 4002h and 4006h After a VM application calls Enable VM Assisted Save Restore the VDD no longer memory across screen switches It INT 2F Extensions 409 becomes the application s responsibility to completely reinitialize video memory after a Notify Foreground Switch request Interrupt 2Fh Function 4001h Notify Background Switch Notifies a VM application that it is being switched to the background The VM application can carry out any actions but should do so within 1000ms This is the amount of time the system waits before switching the application Call with AX 4001h Return value This function has no return value Comments After switching to the background the application continues to run unless it attempts to access video memory If the video adapter is in a video mode that the virtual display device VDD does not support in the background the VDD freezes the application until the application can be switched back to the foreground VM applications that have called En
489. tected mode handler beware of various constraints Chapter 11 introduced this topic Example Protected Mode ISR Code The structure of the Protected mode ISR in each case is somewhat different This is the same example ISR from Chapter 10 1 runtime jisr for prot mode interrupts via idt int 60h call old vector it was saved in int 60 for convenience pusha push ds push es mov ax cs hwndcs post message to window push ax push WM_USER push 0 push 0 push 0 call POSTMESSAGE mov es cs dsselector for writing to data in code seq POP es pop ds popa iret The ISR for interrupts reflected up from Real mode has jm different structure 5 refer Chapter 11 runtime2 isr for Real mode ints via ivt reflected up to prot mode entered with ds si Real mode ss ip es di Real mode call structure jand interrupts disabled should exit with es di still pointing to Real mode call structure pusha 322 Windows Assembly Language amp Systems Programming push ds pusin es get addressability of data in code seg mov ax cs hwndcs post message to window push ax push WM_USER i push 0 push 0 push 0 call POSTMESSAGE A w mov es cs dsselector for pop es POP ds popa riting to data in code seg for returning to Real mode prog prior to interrupt cld lodsw mov eS lodsw mov es lodsw mov es add es i can
490. ted until Windows 3 1 made it official Direct Video You dont want to stuff up the system of course so you need to take whatever precautions are necessary If your Windows application is going to do something drastic like change the screen to text mode then obviously it will not be outputting to a pretty little Windows box The Windows screen will no longer be there This may be ok for what we want but if our program is to work with other Windows programs and with Windows itself then our program must be able to restore the original screen Microsoft does have a very suitable service INT 2Fh AX 4001h Itis summarised in Appendix D described in Microsoft Windows Standard mode 286 mode the linear and physical addresses are one and the same In Enhanced 386 mode an address goes through an extra paging step so the physical address is renamed as the linear address and is no longer the actual physical address SETSELECTORBASE is passed two parameters the selector 16 bits and the starting linear address 32 bits It returns a new selector value in AX or AX 0 if an error 230 Windows Assembly Language amp Systems Programming Directly overwriting the Windows screen Running the screen in text mode Device Development Kit DDK and rather briefly touched on in Writing Windows Device Drivers by D A Norton Addison Wesley USA 1992 Windows Virtual Display Driver VDD uses it to control the act
491. ters for full downward compatibility Here are examples CPU Architecture 23 mov BL 0O examples of different size regs mov BH 0 8 mov BxX 0 16 mov EBX 0 732 _ wo Learning the basic instruction set Coding Specifically for the 386 The E prefix denotes a 32 bit register BX is the bottom half of EBX and BH and BL are the top and bottom halves of BX At this stage I ll present an overall picture of the registers of the CPU The registers shown in parentheses in Figure 1 11 are the portions of the extended registers that are found in the 86 and 286 For example the 86 and 286 have the Stack Pointer SP that is the bottom half of ESP in the 386 The purpose of each register is somewhat more involved than the tiny descriptions given in the figure of course The segment registers are described as being selectors which is valid for Protected mode In Real mode they would hold segment paragraph addresses Note that the 86 286 don t have FS and GS Only AX BX CX and DX can be operated upon in halves that is as AH AL etc This is convenient for handling 8 bit data Instructions It is somewhat back to front but I have given a thorough coverage of the basics of the instruction set in Chapter 2 Therefore if this discussion of registers and instructions is double Dutch to you jump to Chapter 2 then come back here Otherwise keep reading Obviously the 386 has all the instructions of the 86 and
492. th in the IDT with certain qualifications and this example code hooks that vector This point is elaborated on a little later Incidentally if you need to know which mode Windows is running in there is a function that will do that for you GETWINFLAGS O I havent shown the call to GETWINFLAGS in the example below but in a practical program you could include it What follows is just an extraction of the bare essentials to get a hardware interrupt working the flesh can go on later Ok now for some code sadd this extra function to the external declarations EXTRN POSTMESSAGE FAR CODE put in the usual WINMAIN function followed by a callback PUBLIC DPMICALLBACK DPMICALLBACK PROC WINDOWS PASCAL FAR hWnd WORD msgtype WORD wParam WORD 1Param DWORD put in the usual CASE structure to process messages but with some additions Put Windows in Standard mode by typing WIN S when loading it That is what it will be anyway if the CPU is a 286 or a 386 with insufficient RAM usually less than 2M 260 Windows Assembly Language amp Systems Programming mov ax msgtype cmp ax WM_CREATE je xcreate cmp ax WM_DESTROY je xdestroy cmp ax WM_USER je xuser ora GEGE aes here is the handling of the WM CREATE case xcreate jwhatever you want plus call installint hooks the vector here is the handling of the WM USER case xuser push ax push dx mov ah 2
493. that the Win32 DLL is named DLL32 First you need to load the 32 bit library ghLib LoadLibraryEx32W d1132 d11 NULL 0 Then you need to get the address of the 32 bit function in this case MyPrint hProc GetProcAddress32W ghLib MyPrint Then call MyPrint passing it the required parameters TestString and hWnd CallProc32W DWORD TestString DWORD hWnd Oxffff0000 hProc 2 2 The hWnd is OR d with Oxffff0000 because this is the way to convert a 16 bit window handle to a 32 bit window handle in Windows NT and 95 If you want to convert a 32 bit window handle to a 16 bit window handle simply truncate the upper word Note that this only works for window handles not for other types of handles You should use the following functions exported by WOW32 DLL WOWHandle32 and WOWHandle16 in all BIOS DOS Windows Services 221 cases rather than relying on this relationship These functions are discussed in the SDK A mask of 2 0x10 is given because we want to pass TestString by reference WOW translates the pointer and we want to pass the handle by value Finally we must free the 32 bit library FreeLibrary32W ghLib NOTE When linking the Windows based application you need to put the following statements in the DEF file indicating that the functions will be imported from the WOW kernel IMPORTS kernel LoadLibraryEx32w kernel FreeLibrary32w kernel GetProcAddress32w kernel CallProc32W
494. the Machine Status Word and in the 386 it is a simple matter of setting a bit in an appropriate way to come back to Real mode However the 286 has no mechanism for returning to Real mode and it has to be done by the incredibly slow method of resetting the CPU which takes several milliseconds This is one of the reasons that the 286 has become history 20 Windows Assembly Language amp Systems Programming INT 15h AH 89h Creation of a GDT Initialisation of segment registers Why have selectors A problem to call Real mode code from Protected mode INT 15h AH 89h is the service that actually transfers control from the Real mode code to Protected mode code Since hardware interrupts must occur if the PC is to continue to operate and the application may need to generate software interrupts see Chapter 2 for the distinction an IDT must be in existence therefore this service needs more housekeeping Just to give an idea of what goes into a GDT Figure 1 9 shows a basic GDT as required for INT 15h AH 87h The format shown needs a little modification for 386 systems A point about Figure 1 9 is that our application needs to create a GDT and maybe an IDT and put their addresses into the GDT prior to invoking INT 15h But when the service performs the transfer to Protected mode it loads the other descriptors for DS ES SS and CS into the GDT The DOS service will put selectors into DS ES SS and CS insid
495. the mathematics is in order before I throw more words at you like hex byte ascii and BCD You also need to understand the concepts of address and data The computer has memory called either RAM or ROM in which information is stored Floppy and hard disks also store information This information can be either data such as documents that have been typed in or programs such as a word processor All information is stored in the computer as binary values that is as l s and 0 s The computer s memory whether RAM ROM floppy disk tape or hard disk records information in groups of 8 bits That is each memory location contains 8 binary bits Furthermore every memory location is addressable which is logical since the computer must be able to store and retrieve the information from each location So there is an address which is a binary number and it references a location which is an 8 bit binary code This is shown pictorially in Figure 1 1 So what does 00110100 mean 00110100 in Figure 1 1 is just a string of binary bits stored in memory but the PC will interpret it in some meaningful way There is a pictorial answer in Figure 1 2 CPU Architecture 7 Figure 1 1 A memory location Memory addresses from zero to Typical cat content of one million a memory or more location Figure 1 2 Interpretations of a memory content Other codes 00110100 or Unsigned or 2 s complemen
496. the same line and before a string instruction It means check if CX 0 if not perform the string instruction decrement CX then start again Example mov cx str_length A variation on this is REPNE which is basically the same but will also terminate if the zero flag is set REP variations are summarised in the Appendices LOOP Note that the LOOP instruction can do much the same as REP instruction Again CX is decremented before CX is compared with zero so MOVSB will be executed exactly the number of times originally loaded into CX The loop will terminate with CX 0 There are some variations on the basic LOOP instruction have a look in Appendix A mov cx str_length Basic Assembly Language 49 again code loop does same as above movsb i loop again loop is an actual instruction One warning with LOOP is don t initialise CX to zero before entering the loop as it will then loop around 65 000 times When to use LOOP rather than REP LOOP is not restricted to the string instructions because it is an instruction in its own right whereas REP is only an instruction prefix designed to work with the string instructions LOOP can be used wherever a program loop is required and more than one instruction can go inside the loop though note that LOOP can only do a SHORT jump MOVSB Transfer contents byte or word of source pointer DS SI to MOVSW location specified by destination pointer ES DI hence the name Source Index an
497. the simple use of the STDCALL language qualifier takes care of everything By Barry Kauler 1997 Companion Disk Windows Assembly Language amp Systems Programming W32DEMO ASM gt W32DEMO EXE Windows 95 demo program This skeleton assembly language program has been written for TASM5 0 It has the startup code built in rather than as a separate object file 386 MODEL FLAT STDCALL UNICODE 0 this equate used by W32 INC INCLUDE W32 INC equates structures prototypes 32 bit Ring 3 311 IDM_QUIT EQU 100 menu identifiers must be IDM ABOUT EQU 101 same as defined in RC file DATA hInst DD 0 mainhwnd DD 0 s1 WNDCLASS lt gt s2 MSG lt gt s3 PAINTSTRUCT lt gt szTitleName DB Win32 Assembly Language Demo Program 0 szClassName DB W32DEMO 0 sziconname DB ICON_1 0 name of icon in RC file g_hwnd DWORD 0 g message DWORD 0 g_wparam DWORD 0 g_lparam DWORD 0 szaboutstr DB This is an about box 0 messagebox sztitlestr DB Barry Kauler 1997 0 call GetModuleHandle NULL mov hInst eax initialise the WndClass structure mov sil w style CS_HREDRAW CS_VREDRAW CS_DBLCLKS mov sl1 w_lpfnWndProc offset ASMWNDPROC mov si w_cbClsExtra 0 mov s1 w_cbWndExtra 0 mov eax hiInst mov sl w_hInstance eax call LoadIcon NULL IDI_APPLICATION loads default icon NO let s load a custom icon call LoadIcon hInst OFFSET sziconname mov sl w_hIcon ea
498. the so called Real mode 272 Windows Assembly Language amp Systems Programming Virtual video RAM Mapping virtual address to physical address Multiple VMs means multiple IVTs and DOSApps You think of Real mode as using the segment offset addressing method without any of the memory management features and restriction to the first 1M That is quite true for Windows Standard mode because to run a DOS program Windows switches the CPU back to Real mode But in Windows Enhanced mode to run a DOS program the CPU is not switched back to real Real mode Instead it is switched to virtual 86 mode This can have unfortunate repercussions for those of us wanting direct access to hardware I wrote in Chapter 9 about obtaining a selector to video RAM and writing directly to it you will have gained the impression that that is what really happens and I didn t want you to think otherwise However with Windows in Enhanced mode what you are really doing is writing to a virtual video RAM In practise it worked because Windows mapped the virtual video RAM directly to the actual video RAM which is the normal situation for WinApps running in the system VM However the potential is there to cause trouble for you Note however that it is possible to directly address the actual physical memory from within a VM see page 344 The idea of a virtual video RAM and a virtual machine in fact many of them is awkwa
499. the state of the current task s DPMI Services 395 registers in the mode which is not currently executing Call with AX 0305h Returns CF clear this function always succeeds AX size of buffer in bytes required to save state BX CX Real mode address of routine used to save restore state SI E DI Protected mode address of routine used to save restore state Int 31h Function 0306h Get Raw Mode Switch Addresses Returns addresses that can be called for low level mode switching Call with AX 0306h Returns CF clear this function always succeeds BX CX real to Protected mode switch address SI E DI protected to Real mode switch address Int 31h Function 0400h Get Version Returns the version number of the DPMI Specification implemented by the DPMI host Clients can use this information to determine which function calls are supported in the current environment Call with AX 0400h Returns CF clear this function always succeeds AH DPMI major version as a binary number AL DPMI minor version as a binary number BX flags Bits Significance 0 O host is 16 bit DPMI implementation l host is 32 bit 80386 DPMI implementation O CPU returned to Virtual 86 mode for reflected interrupts 1 CPU returned to real mode for reflected interrupts 396 Windows Assembly Language amp Systems Programming 2 O virtual memory not supported 1 virtual memory supported
500. there is no restriction to performing direct I O we are in ring 0 and IOPL O remember main code segment VxD_CODE_SEG BeginProc VDEMOD Destroy VM cmp ebx VDEMOD_Owner Destroying device owner jnz short VDM_Exit xor eax eax mov VDEMOD_Owner eax no current owner VDM_Exit cic ret EndProc VDEMOD Destroy_VM VxD_CODE_ENDS ee ocked code the callbacks VxD_LOCKED_CODE_SEG BeginProc VDEMOD_Control Control_Dispatch Device Init VDEMOD Device Init Control_Dispatch Destroy_VM VDEMOD _Destroy_VM ree EndProc VDEMOD_Control 356 Windows Assembly Language amp Systems Programming VxD_LOCKED_CODE_ENDS P r er ee er ee i OO i a ed Sthe hooked ports get redirected here VxD_CODE_SEG BeginProc My_VDEMOD_Hook firstly resolve contention pushad save regs mov eax VDEMOD Owner get previous owner cmp eax ebx same as current owner jz short process_io yes just handle it or eax eax was there an old owner jz short new owner no mov esi OFFSET32 Device_Name VxDCall Shell_Resolve_Contention jc short dont_process hmmm couldn t resolve cmp ebx VDEMOD Owner if contention winner is the current owner je short dont_process then we shouldn t process new_owner IFDEF DEBUG Trace_Out VDEMOD New Owner EBX ENDIF mov edx 200h our arbitrary port address VMMCall Disable Local_Trapping give winner free access xchg ebx VDEMOD _Owner save new owner get old or
501. there will be a copy of the DOS TSR in the current VM where the DOSApp is running but the TSR is useless The reason is that its purpose is to call the WinApp but it will try to call the Protected mode WirApp in the current VM where it isn t Pll look at this diagrammatically in Figure 11 3 l INT 2FW AX 1685h is described in Appendix D It is for switching VMs CX bit 0 is set to indicate that Windows must wait until interrupts are enabled before calling the callback in the VM bit l is set to indicate that Windows must wait until the critical section is unowned before calling the callback in the specified VM the remaining bits must be zero DX SI the 32 bit amount by which to boost the target VM s priority before changing contexts ES DI the segment offset of the routine to call in the target VM 282 Windows Assembly Language amp Systems Programming Figure 11 3 Execution in System VM from another VM 0 System Virtual Machine A DOS program can look PI V86 at vector 6lh in the IVT mode to get the seg offs addresg of the TSR s ry j The TSR has a IM mechanism for 0 calling Protected mode code in the 5 current VM oo This will crash mode as the Protected 4 3G mode ISR is in the WinApp in 4 The DOSApp has to use the System VM INT 2Fh AX 1685h to pass control back to the System VM and execute the address that it found DOS virtual machines e a ee NJote that the
502. this package It is on the Companion Disk in RADBURN SKELETON ZIP Wayne has produced an very nice help file that explains how the program works His Include file is very cut down without all the equates structures etc I took his file Sven Include file plus some extra stuff and put it together into one file did a lot of editing and ended up with W32 INC He has a bit more code in the startup than my above skeleton and I suggest you examine it and maybe include the same code if you want to use my skeleton for actual projects Postamble Chapter 12 showed how a 16 bit application can move into 32 bit ring O code What about the 32 bit application of this chapter Another question what if the 32 bit application wanted to call a function in a 16 bit DLL Or an interrupt Or perform an IN or OUT instruction It is a strange fact of the historical evolution of Windows that 16 bit applications have greater freedom getting into the insides of Windows than 32 bit applications DOS TSRs also have great advantages Because support for legacy applications is going to continue for the forseeable future it is sensible to use whatever easy paths are available A 32 bit application cannot use the technique of Chapter 12 The reason is that the interrupt handlers provided by Windows for certain interrupts assume that it is 16 bit code executing the interrupt The most fundamental problem is that it is only a 16 bit stack so the interrupt ha
503. three buses The CPU has to put the appropriate address of the printer output port onto the address bus and then the CPU will have to put the data onto the data bus The essential point here is that the address and data buses are being used for two different purposes So how do the various chips that are connected to the bus know whether the current operation is an I O port access or a memory access After all they are all wired onto the same bus as Figure 1 3 shows Control Bus To understand the problem introduced above of how the bus performs access to two different kinds of chips memory and I O it is necessary to have a closer look at the control bus First look at Figure 7 1 Also look at Figure 7 2 For a memory access say to read the next instruction the CPU goes through what is called a machine cycle which simply means it reads or writes memory There is also such a thing as a null cycle in which the CPU is doing something within itself for that clock period When the CPU wants to access the memory it puts an address onto the address bus at the beginning of the cycle then it puts ALE low to let the rest of the system know there is a valid address Depending upon whether the CPU wants to do a read or write operation it pulses MEMR or MEMW low In the case of a PC Hardware 181 memory read it would send MEMR low which tells the memory chips that they are supposed to send data to the CPU The
504. tion that is parameters are pushed from right to left C and stack cleanup is done by the called function Pascal ASM DEF RC MAK Source files needed _1 0 icon file INC H Include files Opening Windows 73 Other functions are available in other DLL and DRV files many of them undocumented and I ll take you a little bit of the way into this uncharted but very exciting territory The Mechanics of Assembling and Linking It is instructive at this point to consider the path we need to traverse to get from our modest little first program written using a text editor to the final EXE program that hopefully won t crash The steps shown here look pretty awful but in practise you ll find it s a cinch The main problem is that we need to produce many more files than the program source file e ASM Your source program s e DEF Module definition file e RC Resource script s e MAK Make file You can produce all of these using a text editor though there are some special programs that help generate them automatically In practise more file types may be required than I list above but for now we are working toward a simple skeleton program only An example of another tile is the icon for your program the graphic image of this would be in an ICO file Figure 3 2 shows a picture of the steps involved I mention the C compiler and C source file here but it could be any language or n
505. tion tile defines various program parameters that the linker needs to generate the EXE tile What we call static library functions can be linked into the EXE and become a permanent part of it which is the way things work in the DOS world However the Windows library functions get linked in without actually adding to the size of the EXE That is they stay where they are and are only loaded into RAM memory when the program executes This keeps EXEs small This kind of library is called a dynamic link library Two Steps for Resources The RC resource file defines parameters connected with the windows icons menus dialog boxes and segments The resource compiler is run twice first to compile the RC file s and second to combine the EXE from the linker with the compiled resources to produce a final EXE Opening Windows 75 After the first compilation it becomes a RES file which has the information in binary form With recent LINK programs there is support to perform the final step by the linker That is the RES file is fed to the linker Windows Programming Mechanics There are some major philosophical differences between Windows programming and conventional DOS based programming It is useful to start off with some appreciation of some new terms intrinsic to Windows objects handles instances messages and callback functions These give us the mechanics of programming in this environment that is they are too
506. to FS and have put DS 30h the GDT FLAT data selector There is no problem with accessing all the data in ASMRINGO using FS ring 3 selector or DS In the latter case we would also have to add flatdatalin INT 20h Notice the peculiar method for calling a VMM or VxD service by means of an INT 20h instruction followed by a couple of parameters Inserting data directly into the code may seem odd but on the first execution pass Windows modifies these three lines and replaces them with a CALL The first parameter specifies which service to call and the second parameter specifies which VxD These are simple equates defined in VMM_INC or in my cut down version VMM TINY INC on the disk Note also that GETDESCRIPTORQO uses the standard C calling convention which means that parameters are pushed right to left and the stack must be cleaned up after return 32 Bit Ring 0 305 Moving On To be able to go up to ring O from inside a ring 3 application is real neat This chapter also showed how to go from a 16 bit segment to a 32 bit segment and actually have them overlap that is be the same segment fitting the SMALL memory model The work done in this chapter can also be applied to Windows 95 native 32 bit applications in which case the segment is already 32 bits but the ring transition is still required It may be perverse but I really like the idea of writing 16 bit applications that have 32 bit and or ring O funct
507. to offsets from the segment start In assembly language the period means exactly the same as so the first code example is really moy ax winl 10 same as mov ax winl field2 Field The assembler will add the offset of winl to 10 and assemble the result as the operand with non immediate addressing encoded into the operation code Thus at execution time the content of field2 will get loaded into AX You will see from the listing that the structure declaration initialisation initialises the values These initialisations will be put into the instances unless overridden In some languages the structure definition is called the object and an instance is called an instance object Basic Assembly Language 67 Overriding by the instances is done by placing values between the lt gt as shown in the code on page 65 Nothing between lt gt means leave original values as they are In the examples of win and win2 I have overridden the original values but should I have decided to override some but not all values I would have put something like this lt asdfgh 55 gt This will leave field2 alone Postamble There are a host of other considerations for assembly language programming for Windows but hey why should I throw it all at you at once Enough is enough Opening Windows Triple purpose of this book Content of this chapter Preamble You ll find this book a nice way for beginners to
508. to recognize the message loop below Usually WinMain will have instance initialisation and window creation code in here but I have shifted it out to make via kickstart This enables me to make as many windows as I want and also enables me to bring out only the essential part of the program to the front end This diversion is implemented via the above CALL loopback call TRANSLATEMESSAGE PASCAL ss di call DISPATCHMESSAGE PASCAL ss di messageloop lea di ms call GETMESSAGE PASCAL ss di null null null Or ax ax j ne loopback Mov ax Fail MSWPARAM return wparam to windows ret WINMAIN ENDP Program Design 165 One callback There is nothing new about the message loop Remember how for all Windows calls GETMESSAGE to get a message from the windows applications queue then calls DISPATCHMESSAGE to send it on to the callback function Because each window has its own callback function we have to design the program so that the message will end up at the correct callback except that in this program there is a trick There is only one callback function called exportwndproc It is a common practise with Windows programming to reuse one set of code with different data for each window Most Windows programs can have multiple instances that is multiple copies running simultaneously without conflict even though they use the same code Each time you double click on the applications icon a new data stack h
509. to the hardware Chapter 4 introduces the VxD and gives references I recommend that if you want to delve deeply into VxDs you purchase a specialised book However it is appropriate for me to explain a little more about how the example VxD in directory TSR2WIN on the Companion Disk works The VxD is VDEMOD ASM and it assembles and links to VDEMOD EXE Note the extension EXE rather than 386 that most VxDs use This relates back to how the VxD is used in Chapter 14 that is it is invoked from the DOS prompt prior to Windows loading which executes the stub TSR2WIN EXE Note that TSR2WIN EXE was inserted into VDEMOD EXE by the linker so it is not a separate program Note that I have created a Make tile to rebuild everything called BUILDALL MAK This is designed for NMAKE EXE and uses the A switch For now however I am interested only in the VxD VxD tools To assemble and link the example VxD requires the DDK or VxD Lite More specifically the following files are required DEBUG INC SHELL INC VMM INC LINK386 EXE LINK4 EXE MAPSYM32 EXE MASMS EXE ADDHDR EXE These are not the standard LINK and MASM version 5 they are special versions Make file TIl start by looking at the Make file VDEMOD MAK This Make file build VDEMOD ASM into VDEMOD EXE and puts in the dos stub TSR2WIN EXE Note that VDEMOD EXE does not have to be in the windows SYSTEM directory The dos stub is to be executed from the aut
510. to two major portions getting at Real mode code from Protected mode in the first half and vice versa in the second half Accessing Real Mode from Protected Mode Recently someone came to me with a problem They had ported a Pascal program from DOS to Windows which was quite easy using the excellent Borland tools but the program didn t work The problem was traced to a section of code that looked at a certain interrupt vector which was a pointer to an interrupt routine But at a certain offset in this routine is some data that the program accessed The code used INT2 1h AH 35h to get the vector but of course you and I know that the vector will come from the IDT not the IVT running in Protected mode Figure 11 1 Figure 11 1 Interrupt deflection to Real mode Windows application Windows handler Original Real mode routine below 1M IRET The INT 21h AH 35h retrieves the vector from the IDT When an interrupt occurs the IDT points to a special handler that passes control to the Real mode DOS routine pointed to by the IVT and Real Mode Access 269 remember that the IVT is located at Real mode address segment offset of 0000 0000 The routine terminates with IRET which will bring it back to the Windows handler which will change the CPU back to Protected mode and then return to your program Accessing Real Mode via the IVT Solution So my advice to this person was you have to look in the IVT
511. tor in idt mov ah 35h int 21h returns vector in es bx mov offsetint bx save old vector mov selectorint es mov dx OFFSET runtime snew vector push ds save ds push cs pop ds new vector in ds dx mov al 16h int to be hooked mov ah 25h set vector int 21h pop ds restore ds ret install ENDP Ce S aa 252 Windows Assembly Language amp Systems Programming INT 21h AH Some interesting points arise from this code INT 21h AH 35h 35 25h IDT vs IVT The rest of the WinApp fixed vs moveable segments DATA CODE or 25h are functions for getting the interrupt vector and for setting it Look back to the special note on how these work with Windows on page 200 It is most important to know that they work on the IDT not the IVT When the CPU is running in Protected mode an interrupt will cause the CPU to look in the IDT to find the selector offset of the interrupt routine In the code above I have not hooked the old INT 16h routine in the IVT I have only hooked INT 16h in the IDT which for normal Windows programs isn t used Notice in the above code that I saved the old vector This is in case I want to call it or jump to it possibly from within the new interrupt service routine Having done that all that remains is to go into the usual message loop as per a normal program which returns control to Windows There is one little complication with this since the vector has been hooked don t close
512. tor offset of exception handler Returns if function successful CF clear if function unsuccessful CF set AX error code 8022h invalid value BL not in range 0 1 Fh 8022h invalid selector Int 31h Function 0204h Get Protected Mode Interrupt Vector Returns the address of the current Protected mode interrupt handler for the specified interrupt Call with Ax 0204h BL interrupt number Returns CF clear this function always succeeds CX E DX selector offset of exception handler Int 31h Function 0205h Set Protected Mode Interrupt Vector Sets the address of Protected mode handler for the specified interrupt into the interrupt vector Call with AX 0205h BL interrupt number CX E DX selector offset of exception handler Returns if function successful CF clear if function unsuccessful CF set AX error code 8022h invalid selector DPMI Services 393 Int 31h Function 0300h Simulate Real Mode Interrupt Simulates an interrrunt in Real mode The function transfers control to the address specified by the Real mode interrupt vector The Real mode handler must return by executing an IRET Call with AX 0300h BL interrupt number BH flags Bit Significance 0 reserved for historical reason must be zero 1 7 reserved must be zero CX number of words to copy from Protected mode to real mode stack ES E DI _ selector offset of real mode register data structure in the foll
513. try Point This function can be called in Real mode only to test for the presence of a DPMI host and to obtain an address of a mode switch routine that can be called to begin execution in Protected mode Call with Ax 1687h Returns if function successful 0 BX flags Bit Significance 0 0 32 bit programs are not supported 1 32 bit programs are supported 1 15 not used CL processor type 02h 80286 03h 80386 04h 80486 05h FFh Preserved for future Intel processors DH DPMI major version as a decimal number represented in binary DL DPMI minor version as a decimal number represented in binary SI number of paragraphs required for DPMI host private data may be 0 ES DI segment offset of procedure to call to enter Protected mode if function unsuccessful DPMI Services 389 FORMAT Heading Call with no DPMI host present AX nonzero Int 31h Function OOOOh 4llocate LDT Descriptors Allocates one or more descriptors in the task s Local Descriptor Table LDT The descriptor s allocated must be initialized by the application with other function calls Call with AX OOOOh CX number of descriptors to allocate Returns if function successful CF clear AX base selector if function unsuccessful CF set AX error code 8011 h descriptor unavailable Int 31h Function 0001h Free LDT Descriptor Frees an LDT descriptor Call with AX OOOlh
514. tself is used as the target address to jump to Addressing modes have been introduced on page 44 Another kind of label is the procedure name as shown here routinel calling a procedure PROC the procedure body goes in here must have explicit ret ENDP Procedures allow you to organize code into structured modules that can be called from a main procedure In some languages they are called subroutines A function is a special case of a procedure that returns a value via a register For example C functions return a value in the AX register or DX AX register pair though when writing C programs you don t know this underlying mechanism of the registers The point I want to make here is that procedure names are treated by the assembler just like code labels In the above example routinel PROC could have been replaced by routinel in which case the routine ENDP would not be needed since it is a syntactical requirement to match the PROC directive 58 Windows Assembly Language amp Systems Programming Data Labels Data labels define constant or variable data including numerical values strings arrays and pointers strl DB message 0 defining an ascii string varl DW56 define word 16 bits ptrl DW789 var2 DDO define doubleword 32 bits aryl DB64 DUP 0 array of 64 bytes Normally we would think of data as belonging in the data segment where the code normally expects to access it but it could ju
515. ture call BEGINPAINT PASCAL hWnd ss ax mov hDC ax hDC display contex call SELECTOBJECT PASCAL ax hOemFont call TEXTOUT PASCAL hDC 10 20 ds OFFSET sout 11 lea ax s3 far addr of paint structure Cad ENDPAINT PASCAL hWnd Ss ax jmp SHORT xbreak cmp WORD PTR 1 Param 0 low half of lParam jne xbreak test if a menu message cmp wParam IDM_QUIT wParam jne notquit im xXQuitmessage notquit cmp wParam IDM_ABOUT jne xbreak sno other menu items call MESSAGEBOX PASCAL hWnd SEG szabout OFFSET szabout SEG sztitle OFFSET sztitle MB _OK xbreak sub ax ax returns 0 in DX AX cwd return a 32 bit long value xretu urn ret WinasmlProc ENDP END MODEL Directive Talready introduced the MODEL directive on page 111 and made reference to the TINY SMALL MEDIUM COMPACT and HUGE memory qualifiers The MODEL directive can also take other qualifiers for example MODEL SMALL PASCAL 120 Windows Assembly Language amp Systems Programming This sets the defaults for the program and PASCAL means that all procedures are to be of Pascal type which also means that the PASCAL qualifier is not needed in the PROC declarations However high level CALL instructions still need language qualifiers to pass parameters automatically so leave the PASCAL qualifier in The choices of language qualifier are PASCAL C BASIC FORTRAN PROLOG STDCALL or NOLANGUAGE The formal syntax for MO
516. u can use the Borland TLINK and COWS OBJ CWS LIB and IMPORT LIB library files instead of the Microsoft equivalents if you wish You only need to change one line in the Make tile that of the assembly process ML c fn ASM where c suppresses linking ML normally automatically invokes the linker and fn is the macro for the filename If you want debugging information so the source file can be traced by the Codeview debugger then you will need the Zi switch and you will need to use Microsofts LINK with the CO switch the example Make tile on the Companion Disk to show this is named MASM60 MAK This is the command line I used to generate WINDOWS INC from WINDOWS H H2INC C Gc WINDOWS H 132 Windows Assembly Language amp Systems Programming MASM6 Program Listing ASMDEMO2 ASM gt ASMDEMO2 EXE Windows demo program This skeleton assembly language program has been written for Microsoft MASM ML EXE v6 1 Do NOT use Borland s TASM It uses PROLOGUE INC to force the correct Windows prolog epilog on all FAR PROCs This program does NOT have the startup code built in Note that Borland provide startup object module as COWS OBJ small model and Microsoft provide APPENTRY OBJ with v6 1 One of these must be linked Note that APPENTRY OBJ should be for the small model to suit this program if not assemble APPENTRY ASM with switches as described in APPENTRY ASM comments MODEL SMALL
517. ual non virtual display driver Basically it saves the adaptor registers 1t works and is dam useful so I have used it in this example code The complement of the above is available also INT 2Fh AX 4002h which tells the display driver to take back control Mighty handy So far you know how to w rite directly to the video RAM and you have a selector to do it with It may be that you dont want to save the screen at all you just want to scribble all over what is already there Perhaps if you want some little message to appear on the screen independently of everything else that Windows is doing on the screen then yes go ahead see page 239 At the moment Im thinking more along the lines of taking over the screen directly for very fast video output such as games or where text mode is good enough or preferred To save the current video state mov ax 4001h Note that undocumented DEATH does this int 2Fh also plus switches screen to text mode The next obvious step is to change the video mode There are some interesting thoughts here Wont Windows and other applications expect to be able to output to the screen also Yes they will but always remember that Windows 16 bit task management is non preemptive This means that once Windows has passed control to your program you can keep control for as long as you like You can lock out other applications and do whatever you want Normally when Windows sends a me
518. uanorou ionene io 89 Resource and Definition Files 0 0 89 Message Format seses ensruitenauats wid cee als oun aceu wane wes 90 Make Fler irea t remas aoise arad ea E sna raraees 91 Development Cycle corssier nnii sa ILERE AAEE KEE 92 Application Structure seit cst eee beet eiatehertetatelbad ene 94 Pre liminary COME serasi AEA A AAAS 94 Startup Code seriet raria taa EAEE ERE EE 96 WIN MAING eisena e eek wee eens 98 Callback Function 62445 fore fan tietnn ei aete be ea es 102 5 High Level Assembly 109 Preamble sata icine we eeed Cys e TER REE Den ie 109 Tjclude PUES inasi we aerate nna et aaa ne eens nena eae 109 Microsoft versus Borland ccseeeeeeeeeeeees 110 Skeleton Analysis cccvsscecwoanes A tits 6 Wyk E 111 IMODED Ditective ciakc it weiws pea ee EA 119 Private and Global Data svacciusvetsasenet goeueueax ieee 120 MASM versus TASM Scope seeeeeeeereeeeeeee 121 TASM S O ere ease teenie ness eae 121 Life of Automatic Datacc cie4tiaeat cesta det Goosen 122 Assembling and Linking esse cece center e eee e ences 123 MASMG6 versus TASM wacsscseoe eeeaeterd aaa sere eee ay 125 WINDOWS Qualifier eiuseavisvetaest sacs contascieus 126 Prot types ntsc chs cas aun G eases sawed os ee teens 127 Callback Desi en Larae a a NA leas 129 Other Incompatibilities ssresesrersrrrreserrerre 130 MASM Assembling and Linking e0eee 131 MASM6 Program Listing oo cece ce
519. unicate and share data This chapter This chapter is a mixed bag I have likened the learning process to climbing a ladder as illustrated in Figure 15 1 This book is intended to satisfy all the alternative needs of the pondering man sitting with hand to mouth It is the nuts and bolts not the latest high level techniques such as programming using visual 00 components in Borland C Builder Move onto those tools if you want and you may well do to produce major applications You may also move deep into VxDs and again I ve led you to the point where you can jump in to the brink so to speak I also make no apologies for focusing strongly on 16 bit programming and the software interrupt services as the needs of our pensive man in Figure 15 1 will remain valid for many years to come What I do need to do in this last chapter is fill in a few gaps and make some suggestions After that go where you will Advanced Systems Programming 343 Figure 15 1 The ladder of learning I know DOS programming it s about time I got into Windows All I know is assembly language how on earth can I learn to program for Windows Ive got this DOS application CH it overdue for porting to Windows Object orientation Im a student and I want to learn the Virtual device drivers nuts and bolts before progressing Windows 32 bit architecture to C etc Virtual machines Transitions between DOS Windows I v
520. urns if function successful CF clear if function unsuccessful set AX error code 8025h invalid linear addreses range unallocated Int 31h Function 0703h Discard Page Contents Discards the entire contents of a given linear memory range This function is used when a memory object such as a data structure that occupies a given area of memory is no longer needed so that the area will not be paged to disk unnecessarily The contents of the discarded region will be undefined Call with AX 0703h BX CX starting linear address of pages to discard SI DI size of region to discard bytes Returns if function successful CF clear if function unsuccessful CF set AX error code 8025h invalid linear address range unallocated Int 31h Function 0800h Physical Address Mapping Converts a physical address into a linear address This function allows device drivers 2 running under DPMI hosts which use paging to reach physical memory that is associated with their devices above the 1 MB boundary Examples of such devices are the Weitek numeric coprocessor usually mapped at 3 GB buffers that hold scanner bit maps and high end displays that can be configured to make display memory appear in extended memory Call with AX 0800h BX CX physical address of memory SI DI size of region to map bytes Returns if function successful CF clear BX CX linear address that can be used to access
521. uses Now if you are up to some binary calculation this means that the possible range of addresses is from zero to 2 1 In binary that is an upper limit of 1111111111111111 or in hexadecimal FFFF or in decimal 64 1024 1 65 535 We normally refer to this memory capacity as 64K where K represents times 1024 note that a megabyte is 1024 1024 so 1M 1 1024 1024 1 048 576 bytes The upgrade from 16 to 20 bit address bus 16 bit IP Matches a 16 bit address bus Byte addressing How segments started CPU Architecture 15 Figure 1 6 16 bit addressing prior to the x86 family 8008 Z80 CPU Address bus Instruction Pointer IP The Intel engineers thought that with the 8086 family they would increase the memory capacity to something more than plenty so they gave the 8088 and 8086 a 20 bit address bus 22 IM A million or so bytes of memory seemed like an enormous amount at the time but this has turned out to be a serious limit and constitutes half of our headache The other half of the headache is how the engineers designed the chip to address that 1M They wanted to make it easy to port software from the 8 bit CPUs Internally those earlier CPUs have an Instruction Pointer IP which is a register that marks the address of the next instruction to be executed It is 16 bits to match the externa address bus Note that each memory location as addressed by a unique address is 8 bits
522. ve 32 bit WinApp to thunk down to 16 bits to use the interrupts Thunking is introduced in Chapter 8 34 342 Windows Assembly Language amp Systems Programming 32 bit Actually Chapter 12 describes how a 16 bit application can go to WinApp 32 bit ring 0 It is interesting that Matt Pietrek in Windows 95 access to Systems Programming Secrets IDG Books 1995 describes a ring 0 32 bit WinApp that goes to 32 bit ring 0 but he does it by thunking down to 16 bits and using the same techniques as Chapter 12 It is amusing to see that Matt often has to resort to assembler due to the awkwardness of C Thinking Chapter 14 showed how a DOSApp can get its hooks into a 16 bit further about WinApp and a VxD but this could also apply to a 32 bit WinApp Chapter 14 It is quite feasible for a 16 bit WinApp to load do all the low level dirty work such as getting selectors to forbidden areas then call WINEXEC to load a 32 bit WinApp It is possible to pass parameters to a 32 bit WinApp via the command line and really easy to insert them into the argument passed to WINEXEC You could have a 16 bit WinApp and a 32 bit WinApp there is no need for a DOS TSR and run the 16 bit WinApp first Demo code for I dont have the room to put a detailed description into this 16 and 32 bit chapter but there is demonstration code on the Companion Disk WinApp in directory SHAREALL that shows how a 16 bit WinApp and communication a 32 bit WinApp can comm
523. verride all of the message handlers for the CONTROL class so that they just return without doing anything Anyway Ive kept this code as simple and as elegant as possible Getting it Together One thing you may be starting to appreciate is that Windows adds an incredible processing overhead even a simple key press has to go through so many steps before it reaches the destination Then we go and make things even worse by using 00 techniques that add yet another layer of processing If you want code that rockets along for a video game for example you will want to know mechanisms for speeding things up OOP may make the coding easier but it may be going against a fundamental reason why we are using assembly language Let me post this as a thought for now Oh yes the WINASMOO MAK file has a couple of minor changes from before so here is the listing this Make file has been modified for Borland C to be used with TASM and TLINK however Im still using Microsofts NMAKE as Borlands MAKE has some strange though the version e ae v3 0 ity wit oe os fn winasmoo all fn exe 176 Windows Assembly Language amp Systems Programming lpath borlandc lib path for libraries ipath borlandc include path for Include files epath borlandc bin path for EXEs sw e n v Tw L lpath switches for tlink n ignore default libs Tw generate Windows exe Le lpath lib path v debug on fn obj fn asm
524. ves information about the first module associated with a Win32 process e Module32Next Retrieves information about the next module associated with a Win32 process or thread e Process32First Retrieves information about the first Win32 process encountered in a system snapshot e Process32Next Retrieves information about the next Win32 process recorded in a system snapshot e Thread32First Retrieves information about the first thread of any Win32 process encountered in a system snapshot e Thread32Next Retrieves information about the next thread of any Win32 process encountered in the system memory snapshot Toolhelp32ReadProcessMemory Copies memory allocated to another process into an application supplied buffer river What follows are functions available inside the drivers They unctions cannot be called directly as you would a normal Windows function but require an extra step See the practical code in the Chapter 9 Also they are not documented in the SDK 216 Windows Assembly Language amp Systems Programming Mouse driver functions COMM driver functions INITIALIZATION Initialises the mouse device driver DISABLE Suspends interrupt callbacks from the mouse device ENABLE Enables calls to the Windows mouse event procedure INQUIRE Gets information about the mouse characteristics MOUSEGETINTVECT Gets the interrupt level used by the mouse hardware WEP Performs cleanup when the Windows session ends
525. w supplied with the SDK v3 1 or on the on line documentation supplied with the SDK This reference has definitions for each of the above functions plus explanation of the startup sequence It is instructive to consider what the status is when Windows calls start incidentally scan ahead to the very end of the program and youll see that termination is with END start which is standard practise for DOS programs and defines the starting point of the program start is entered with the CPU registers set as per Table 4 2 However INITASK returns its own information in the registers as per Table 4 3 which are passed as parameters on the stack to WINMAIN Table 4 2 Registers at entry to application Register Value Ax Zero BX size in bytes of stack cx size in bytes of heap DI handle of application instance SI handle of previous application instance BP zero ES segment address of PSP DS segment address of automatic data segment SS same as DS register SP offset to first byte of application stack Table 4 3 Register values returned by INITTASKO Register Value AX 1 ok zero error ES BX FAR address of the DOS command line cx stack limit in bytes DI instance handle of new task SI handle of previous instance of program 98 Windows Assembly Language amp Systems Programming DX nCmdShow parameter ES segment address of PSP INITTASK also fills the first 16 bytes reserved in
526. want to write Windows programs but dont want to give up the advantages of Real mode and of text mode video The product is called Mewel and it is a complete library for writing Windows applications that run without Windows under DOS in Real mode or Protected mode with the screen in text mode or graphics mode Its a lovely product and works well The only major deficiency is that there is no multitasking Mewel even allows source code to specify Magma Systems 15 Bodwell Terrace Millburn New Jersey 07041 USA http www uno com magma html 228 Windows Assembly Language amp Systems Programming standard Windows screen coordinates so a stock standard Windows program will compile and run under Mewel Mewel applications are stand alone as the library files are linked statically But it does mean that a simple Hullo world program is about 100K Mewel even manages to represent icons in text mode Addressing memory below Back to the main topic Let your first challenge be to directly 1M in Protected access memory No problem DPMI has INT 3 1h AX 0002h mode DATA oO00Oselector DW 0 selector addr O BOoOOOselector DW 0 selector video RAM CODE mov ax 0002 supply a segment returns a selector mov bx B0O00h segment addr of video RAM int 31h mov BOOOselector ax save selector mov ax 2 get selector for segment addr 0000 mov bx 0000h start of physical memory int 31h mov OO0Oselector ax save la
527. wer up the PC It is a nice place to start from when we sit down and turn on the computer What happens behind all that whirring of the hard drive and text and graphics flashing on the screen Power on Load bootstrap program from BIOS ROM Load another bootstrap program from the Boot Record on the disk Which loads the system files from the disk Finally COMMAND COM executes and the DOS prompt appears OR WIN COM executes and Windows loads TE 10 SYS MSDOS SYS COMMAND COM WIN COM The boot sequence You must have a system disk in either drive C or drive A that is a disk that contains the files IO SYS MSDOS SYS and COMMAND COM if DOS is to run or WIN COM and the rest of the Windows files if Windows is to run Note that the first two are hidden that is you can t see them with the normal DOS DIR command however they are there in the root directory Note also that on IBM PCs these two hidden files are named IBMIO COM and IBMDOS COM After first turning on your PC or after pressing the key combination lt alt ctrl del gt it will execute a bootstrap program that is permanently stored in the PC s ROM Read Only Memory When this bootstrap program executes it will look at drive C to see if the system files are on it If not or if drive C does not exist it will then look at drive A This second choice is where you have an opportunity to boot from a floppy disk if there is a floppy disk inserted
528. would need them to call C run time functions investigate using startup code supplied by the vendors for correct initialisation the next chapter shows how to link the Borland startup tile COWS OBJ Microsfts MASM v6 1 supplies APPENTRY OBJ Whenever you see the letter S in a library filename it usually means Small model while the letter W designates Windows The Bare Bones 87 Table 4 1 Earliest versions that will generate an executable MASM EXE _ v5 10 TASM EXE C v2 0 LINK EXE v5 10 C v6 00 TLINK EXE C v2 0 NMAKE EXE v1 11 C v6 00 ditto RC EXE v3 00 SDK v3 O ditto RCPP EXE SDK v3 O ditto RCPP ERR SDK v3 0 ditto LIB W LIB SDK v3 0 IMPORT LIB SLIBCEW LIB SDK v3 0 CWINS LIB WINSTUB EXE from the SDK ditto Borland amp other tools Installation of the development fools The second column of Table 4 1 contains the earliest Borland versions that will work Other LINK versions should be ok as long as they are Windows compatible MASM prior to 5 10 should also be ok The normal situation is to have the SDK installed with everything in the appropriate directories The manuals with the SDK C v6 00 and MASM explain how the environment variables need to be set so that MASM and LINK can find the appropriate files Or you could have one of the other development systems installed such as Borland C that do not need the SDK as a separate entity Note also the Microsoft C C
529. write char to sern mov dal 07 beep int 2l1h pop dx POP ax jmp xexit xdestroy call POSTQUITMESSAGE PASCAL 0 unhook the int 5ih push dx push ds mov dx offsetint jthis is the old INT 51 vector mov ds selectorint mov ax 2551h before quitting we are restoring it int 21h pop ds POP dx im xexit wha tever else you want here s xexit sub ax ax returns 0 in DX AX cwd sreturn a 32 bit long value ret DPMICALLBACK ENDP Hooking A WM_CREATE message is sent when the window is first unhooking created so this is a convenient time to hook the vector Therefore the vector a call to INSTALLINT is included Similarly upon exit it is necessary to unhook the vector otherwise Windows will crash Unhooking on receipt of the WM_DESTROY message is most appropriate This code simply uses INT 21h AH 25h to restore the old vector which has previously been saved in offsetint and selectorint by the installint procedure Real Time Events 261 Interrupt Handler Code POSTMES The interrupt service routine will be entered every time a key is SAGE pressed or released and all that I have done inside it is call POSTMESSAGE to send a WM_USER message to the window s callback function DPMICALLBACK WM_USER WM_USER equates to a message number that is not used by Windows as a message so it is free for an application to use A range of such numbers is available for an application to use look in WINDOWS INC
530. x call LoadCursor NULL IDC_ARROW mov s1 w_hCursor eax mov sSl w_hbrBackground COLOR_WINDOW 1 mov sl w_lpszMenuName OFFSET szClassName mov sl w_lpszClassName OFFSET szClassName call RegisterClass OFFSET sl call CreateWindowEx 0 OFFSET szClassName OFFSET szTitleName WS_OVERLAPPEDWINDOW CW_USEDEFAULT CW_USEDEFAULT CW_USEDEFAULT CW_USEDEFAULT 0 0 hInst 0 312 Windows Assembly Language amp Systems Programming mov mainhwnd eax call ShowWindow mainhwnd SW_SHOWNORMAL call UpdateWindow mainhwnd msg_loop call GetMessage OFFSET 82 0 0 0 cmp ax je end loop call TranslateMessage OFFSET 82 call DispatchMessage OFFSET 82 jmp msg_loop end loop call ExitProcess s2 ms_wParam b ee we eer ee ww ee mew Re eR Kw eK X Kw Kw KM ww KM Mw MP MP wm MP Mm Ww Bem eM ew rem em eee PUBLIC ASMWNDPROC ASMWNDPROC proc STDCALL hwnd DWORD wmsg DWORD wparam DWORD lparam DWORD USES ebx edi esi LOCAL hDC DWORD mov eax hwnd useful to make these static mov g_hwnd eax 7 be cautious though as mov eax wmsg sometimes Windows reenters mov g_message eax ASMWNDPROC For example it is mov e ax wparam possible for Windows to call mov g_wparam eax ASMWNDPROC with a WM PAINT mov eax lparam message even though execution mov g_lparam eax jis currently inside ASMWNDPROC alternative is pass these via stack to functions xor eax eax mov ax WORD PTR g message IF ax
531. y After DOS has loaded CONFIG SYS it then looks on the disk for AUTOEXEC BAT Any file with an extension of BAT is known as a batch file and AUTOEXEC BAT is a special batch file that DOS looks for at power up Here is an example of an AUTOEXEC BAT file echo off PATH C C SYSTEM DOS C GALAXY PROMPT p g WIN In a nutshell a batch file is created by any text editor and contains DOS commands as well as special batch commands that enable you to automate the operation of DOS Instead of having to type in the same DOS commands every time you start the computer by putting them into the AUTOEXEC BAT file DOS will execute them automatically for you every time 6 Windows Assembly Language amp Systems Programming Power on self test POST RAM and ROM Byte addressed memory Successive versions of Windows have made less and less use of CONFIG SYS and AUTOEXEC BAT However even Windows 95 will still obey whatever you put in these files The power up sequence of the PC is quite involved and many references are made to it throughout this book Of particular interest is the configuration RAM that the BIOS uses during the Power On Self Test POST sequence The configuration CMOS RAM is a part of the real time clock chip Number Systems Well maybe I shouldn t assume too much knowledge on the part of my reader I m already throwing around words like RAM ROM and boot Perhaps some discussion of
532. y this opens up some possibilities Staying on track for now I used INT 16h AH 0 to get the character back off the buffer and the character I chose was 07 the beep character I sent it to the display using INT 21h AH 2 supplying the ASCII code in DL The beep character doesn t go to the screen however it is treated as a control character all characters below 32 decimal are and in this case causes a beep on the loudspeaker Hence there is immediate feedback that the code has worked The above code works fine at least for calling a BIOS or DOS service but if you want to call code or access data in a DOSApp there are more complications A DOS program DOSApp running under Windows would be running in Real mode in what is sometimes called a DOS compatibility box Windows in Standard mode can only have one of these running at any one time as Standard mode is based upon the capabilities of the 286 CPU which cannot just flip between Real and Protected modes on a per task basis Windows in Enhanced mode is based upon the virtual 86 capability of the 386 which allows multiple DOS boxes or virtual machines Virtual Machines There is a section back on page 29 that introduces the concept of virtual 8086 machines The 386 can happily multitask just about any number of these virtual machines although Windows has a limit of 16 However it does place a caveat on everything I ve written so far about
533. y can even the System VM will have their own extended correctly pass up to the nemory WinApp If you have a look at the DOSApp you will see that it looks at vector 61h in the IVT to get the address of the forwarder routine in the TSR and then it uses INT 2FWAX 1685h to switch over to the system VM and also to execute the forwarder code in the copy of the TSR located in the system VM These little programs are two pieces of the puzzle but there is a third The WinApp has to hook INT 60h in the IVT of the system VM Real Mode Access 283 Hooking a Real Mode Interrupt from a WinApp I have already written a little about this back on page 279 and introduced two DPMI functions that will allow a WinApp to hook a vector in the IVT in the system VM and pass control up to a Protected mode ISR WinApp What your WinApp needs to do is call DPMI function 0201h Set ISR Real Mode Interrupt Vector and 0303h Allocate Real Mode install Callback Address routine Here is an install portion of a WinApp CODE offsetrealint DW 0 zold ivt vector segmentrealint DW 0 A dsselector DW 0 data alias to code seg hwndcs DW 0 save window handle for use in isr callbackbuffer REGSTRUC lt gt Real mode register structure installint PROC no params install pusha push es push ds will create alias in ldt of current task mov ax 000Ah create alias data descriptor for code push cs POP bx selector to be aliased int
534. y means reached the point where we can ignore these issues despite faster CPUs and more memory In fact our programs run slower than ever before and 16M is no longer enough Let me finish this argument by quoting Karl Wright and Rick Schell from Mixed Language Programming with ASM Dr Dobb s Journal March 1990 Tt is not only practical but advisable to mix languages and models in order to achieve the best results Modern assembly language is a vital part of this mix and will continue to be important in the future because space and performance are always important for competitive software no matter how powerful the hardware becomes As a final note I wrote the GOOFEE Diagrammer bundled with my book Flow Design for Embedded Systems R amp D Books 1997 entirely in assembly language It is a 16 bit WinApp a very sophisticated graphics drawing program that is ridiculously small at only 100K By using the high level features of modern assemblers my assessment is that coding time would not have been any faster if done in C nor would it have been any more readable maybe less readable I did use Layout for some of the dialog boxes and mathematics but I found the automatic code generation was doing things I didnt want Hence I rewrote those portions in assembly language also Instruction Summary cnt Reg Mem Accum Imm Deststr Sourcestr Segreg Flags gt Legend 4 flags affected by
535. y pressed call xchar ELSE invoke DEFWINDOWPROC ihWnd imessage iwParam ilParam ret ENDIF sub ax ax returns 0 in DX AX callback functions cwd return a 32 bit long value ret ASMDEMOPROC ENDP xereate PROC call makering0selector invoke GETSTOCKOBJECT OEM FIXED FONT mov hOemFont ax handle to font ret xcreate ENDP aen BROC cmp WORD PTR ilParam 0 low half of lParam Jne zxcv test if a menu message cmp iwParam IDM_QUIT wParam jne notquit call xquitmessage imp ZXCV notquit cmp iwParam IDM_ABOUT jne ZXcCV sno other menu items invoke MESSAGEBOX ihWnd ADDR szaboutstr ADDR sztitlestr MB_OK cli call RINGOCALLGATE will call ring 0 code sti ZXCV ret xmenu ENDP P PROC invoke POSTQUITMESSAGE O call freeourselectors ret xquitmessage ENDP errormsgproc PROC entered with ds si pointing to message invoke MESSAGEBOX handlemain ds si ADDR szerror MB_OK MB_TCONEXCLAMATION ret POOLNE REOC ENDP PO r r O O nr eveeene eaeaeeeeesses 2 Pew E E ee Be E we ee ee rr ee eee E The rest of the message handling code removed 296 Windows Assembly Language amp Systems Programming Creation For this demo program I chose to use the WM_CREATE message of a Call to call makeringOselector which sets up the addressing to the gate ring O code Then I arbitrarily chose to use a press of the ok button on the messagebox which occurred in re
536. y presses will in real time be routed to the ISR and be posted to the iconized program and Windows will call the iconized program s callback function giving it the message even though it is iconized So you ll always get the beeps when pressing and releasing a key However if you run the DOS Prompt program the beeps will stop Upon exiting back to Windows the beeps will start once again 264 Windows Assembly Language amp Systems Programming What the program does 3y Reference sources What is DMA If you really must have the ISR continuing to function when the CPU is running a V86 or Real mode program refer to Chapter 11 as I decided to make the handling of Real mode a special chapter all on its own See also the footnote on page 258 I suppose you do realise by now what the example program does it beeps the loudspeaker every time you press or release a key Because the ISR only posts a message to the main Windows program it is what I would class as pseudo real time response Don t forget however that the ISR shares the same code segment as the main program and by way of a data alias data can be passed to and fro Or the actual WinApp data segment can be readily accessed For example harking back to the problem that my colleagues had they wanted to measure an external parameter at precise intervals and log it for internal analysis The interrupt mechanism provided the precise intervals
537. y programs are present in ROM and if they are subject to certain identification they are immediately executed Thus these programs are able to modify the system to suit themselves The CPU amp Support Chips One step at a time we are focusing for now on the 8086 as that is the mode that all of the x86 family power up into It is the CPU used in the first IBM PC no strictly speaking it was the 8088 The only difference between the two is that the 8088 had an 8 bit data bus while the 8086 had a 16 bit data bus The first PC was Embedded systems Book on design of embedded systems CPU Architecture 13 thus able to use the cheap and readily available interface chips designed for an 8 bit data bus The 8086 is still used not just in PCs but in a host of dedicated embedded controller applications though usually in the latter case it is some derivative of the 8086 So the 8086 is not dead and its presence is to be found even in the very latest Pentium CPUs Why because of the requirement for backward compatibility In fact you may be very surprised I don t have the exact figures but processors for embedded systems far outweigh annual sales for PCs Quite literally billions of processors are manufactured annually for embedded systems This would include humble home appliances such as your washing machine and video player The 8088 would be considered too powerful for most of these applications But you will
538. yboard configuration structure that contains the DBCS ranges e NEWTABLE Loads the keyboard translation tables System CREATES YSTEMTIMER driver Allocates a system timer to be used by a device driver functions GETSYSTEMMSECCOUNT Gets the amount of elapsed time INQUIRES YSTEM Gets various system configuration parameters e KILLSYSTEMTIMER Frees a timer to be used by a device driver Grabber Earlier I described mechanisms for Windows to save and restore functions its video hardware state if an application wants to do something with the video From the application point of view after getting control of the video it can call some functions to manipulate the display driver Calling these functions is not straight forward refer to Writing Windows Device Drivers by D A Norton Addison Wesley 1991 page 79 This reference also has more 218 Windows Assembly Language amp Systems Programming detail on these functions in its appendix D page 247 They are summarised here e DISABLESAVE Disables switching between Windows and DOS sessions e ENABLESAVE Enables switching between Windows and DOS sessions e GETBLOCK Copies the specified rectangular portion of the screen to a buffer e GETINFO Gets the grabbers GRABINFO structure e GETVERSION Returns the grabber version number e INITSCBEEN Initializes the screen to text mode e INQUIREGRAB Gets the size of the text or graphics grab buffer e INQUIRESAVE Gets the si
539. ze of the text or graphics save buffer e RESTORESCREEN Restores the state and contents of the display e SAVESCBEEN Saves the state and contents of the display e SETSWAPDRIVE Specifies the drive and path of the grabber swap file The above group only work in Real and Standard modes The 386 Enhanced mode has a different set of functions Undocumented Many functions available in Windows 3 0 3 1 and 95 are not functions Reference books described in the SDKs nor anywhere for that matter These are undocumented functions which means that Microsoft doesnt want us to know about them see also page 235 There are various chaps who have dug up the dirt and written books Undocumented Windows A Programmers Guide to the Reserved Microsoft Windows API Functions by A Schulman D Maxey and M Pietrek Addison Wesley USA 1992 Unauthorized Windows 95 by Andrew Schulman IDG Books USA 1994 Windows 95 Systems Programming Secrets by Matt Pietrek IDG Books USA 1995 Generic thunking Flat thunking Universal thunking Reference sources Function prototypes BIOS DOS Windows Services 2 19 Thunking The mismatch between 16 and 32 bit code is a major headache Windows internally is also a mixture including Windows 95 especially Windows 95 I have shown in this chapter that some functions available to 16 bit applications are not available to 32 bit applications and vice versa This is because each h

Download Pdf Manuals

image

Related Search

Related Contents

Régulateur à 2 canaux isolés montage rail DIN série deltadue  取扱説明書 - M  Solis Barbecue Grill XXL Pro 792 (FDE)    PDFファイル  Appeal for old mobile phones  Impact of ivermectin-resistant gastrointestinal nematodes in feedlot  Samson CM40 User's Manual  Brochure 450 pages (format PDF, 5Mo)  オフィスサインSシリーズ 取扱説明書 (出退表示システム)  

Copyright © All rights reserved.
Failed to retrieve file