The MASM Forum Archive 2004 to 2012

General Forums => The Campus => Topic started by: Joe Btfsplk on February 24, 2011, 06:26:52 PM

Title: Windows Assembly Language Programming
Post by: Joe Btfsplk on February 24, 2011, 06:26:52 PM
I hope this topic is where we can discuss Windows Assembly Language Programming.

Note that I have ordered the Windows Assembly Language Programmers Guide from Amazon but it isn't here yet.

In DOS Assembly Language I use the following code to get more memory:

      MOV     BX,(No. of 16 byte words I want)
      MOV     AX, 48h
      INT       21H
      JC         ERROR
       (The address of the memory I acquired is in the AX register)

The problem with DOS is that I can't get more than 64K of memory in a segment. I hope that the book I ordered will tell me how to get more than 64K of memory using Windows. If anyone knows how to do it, please post the Assembly Language code it takes in Windows. (Note that I don't see how you can get more than 64K of memory in a segment because the DS, ES, FS, and GS registers are only 16 bit registers. How would you address above 64K of a memory segment?)

Joe Btfsplk
Dinosaur Mainframe programmer
experienced DOS Assembly Language Programmer.
Converting to Windows Assembly Language programming.
Title: Re: Windows Assembly Language Programming
Post by: clive on February 24, 2011, 06:38:16 PM
Unless you are doing 16-bit Windows code the segment size of 64 KB shouldn't be a problem. And you don't want to be doing math on them.

In 32-bit Windows, they are SELECTORS, referring to descriptors in a table, and can describe up to 4 GB of addressing space, although the generally usable range is 2-3 GB. This address space is virtualized through a page table to the physical memory, or page file.

Check the Win32 API functions LocalAlloc(), GlobalAlloc(), HeapAlloc(), VirtualAlloc(), etc
http://msdn.microsoft.com/en-us/library/aa366781%28v=vs.85%29.aspx
Title: Re: Windows Assembly Language Programming
Post by: dedndave on February 24, 2011, 06:41:28 PM
 :bg
in 32-bit code, we use GlobalAlloc, LocalAlloc, or HeapAlloc and related functions
you can grab as much memory as the user has available
64 Kb is considered as a fairly "small" amount

unless a situation requires otherwise, i usually use HeapAlloc...
       INVOKE  GetProcessHeap
       mov     hHeap,eax
       INVOKE  HeapAlloc,eax,NULL,BytesRequired
       mov     hBlock,eax

if you want the memory zeroed, replace the NULL with HEAP_ZERO_MEMORY
hBlock represents the base address of the allocated block
when you are done using it.....
       INVOKE  HeapFree,hHeap,NULL,hBlock

http://msdn.microsoft.com/en-us/library/aa366781(v=VS.85).aspx
Title: Re: Windows Assembly Language Programming
Post by: redskull on February 24, 2011, 06:49:43 PM
Quote from: Joe Btfsplk on February 24, 2011, 06:26:52 PM
Note that I don't see how you can get more than 64K of memory in a segment because the DS, ES, FS, and GS registers are only 16 bit registers. How would you address above 64K of a memory segment?)

In protected mode, the 16-bit values in the segment registers no longer directly point to base addressess; they are integer indexes of a row in an entirely seperate memory-based table (the LDT/GDT), which contain 32-bit base address (among other things).  The CPU does all the calculations, and the operating system maintains the table.

-r
Title: Re: Windows Assembly Language Programming
Post by: clive on February 24, 2011, 06:52:11 PM
This book might be a good place to start with to understand the mechanics of what changed on the x86 when it moved from 16-bit to 32-bit

The 80386 Book by Ross P Nelson
http://www.alibris.com/booksearch?qsort=p&isbn=1556151381

another would be

Programming the 80386 by John Crawford, Patrick P Gelsinger
http://www.alibris.com/booksearch?qwork=5407960

You could also try the current Intel manual set, although I think the older ones might be more helpful to grasp the sea change that occurred. The ones on 386 Systems Programming might be particularly interesting from an OS/Assembler perspective.
Title: Re: Windows Assembly Language Programming
Post by: BogdanOntanu on February 24, 2011, 06:58:17 PM
Also do not forget the VirtualAlloc (and VritualFree/VirtualQuerry) where you usually allocate much larger blocks (64K is a minimum reserve) and at time you have to manage more but you have the option to reserve and commit memory in chunks when you need it ;)

Basically in Windows one does not use INT 21h anymore. Also the use or 16 bits registers like ax,bx is more rare and instead we use 32bits registers like eax,ecx,edx,ebx,esp,ebp,esi,edi. We even have 64bits and 128 bits registers available.

You need to learn how to use the Windows API and 32 bits registers.

With mov eax,[esi] you can theoretically access any memory range from zero to 4G (if you have the rights of course) and because of this the segment registers are not needed anymore.

There is a whole new (and modern) ASM world there.

I suggest that you check Iczelion's famouse ASM tutorials online ...  for a faster intro while you wait for the books you ordered ;). 

BTW... books about modern ASM programming (32bits and 64bits) are rare and not so good anyway because ASM is no longer perceived as a mainstream or even an used programming language of today.

Books can help you with Java and C/C++ and C# and Python but not with ASM. There are not enough people interested in ASM in order to buy (and hence write) ASM books anymore.

Hence you might be forced to learn yourself and/or to ask questions on this forums ;)



Title: Re: Windows Assembly Language Programming
Post by: dedndave on February 24, 2011, 07:07:43 PM
here's that book Clive mentioned in PDF form...

http://ebookee.org/The-80386-Book_558870.html

i just saved you 99 cents   :P
Title: Re: Windows Assembly Language Programming
Post by: clive on February 24, 2011, 07:35:02 PM
Quote from: dedndave
i just saved you 99 cents   :P

And probably $3.99 S/H too. I did try to find a PDF while looking for a cite. Personally prefer real books though.

Anyway consider Alibris, most of the Amazon book sellers are there, and the coupon codes are easier to find.
Title: Re: Windows Assembly Language Programming
Post by: Joe Btfsplk on February 24, 2011, 09:57:28 PM
Quote from: dedndave on February 24, 2011, 07:07:43 PM
here's that book Clive mentioned in PDF form...

http://ebookee.org/The-80386-Book_558870.html

i just saved you 99 cents   :P

I have that book and it's a pretty good book on the architecture of the 80386 (and above) but not much good information on converting Assembly Language programs from DOS to Windows. I hope the book I've ordered does a better job of explaining what instructions to use to replace the INT 21H instructions. I did learn from it that I need to convert all the registers that I PUSH onto the stack into 32 bits so the great sum of $4.50 that I spent on it wasn't completely wasted.

Thanks for your concern about my finances dave!

Joe Btfsplk
Learning Windows Assembly Language,
because Assembly Language is the best language for Systems Software.
(Not very good for applications, COBOL is the best for applications, easyest to follow program logic.)
Title: Re: Windows Assembly Language Programming
Post by: Joe Btfsplk on February 24, 2011, 10:01:51 PM
Quote from: clive on February 24, 2011, 06:38:16 PM
In 32-bit Windows, they are SELECTORS, referring to descriptors in a table, and can describe up to 4 GB of addressing space, although the generally usable range is 2-3 GB. This address space is virtualized through a page table to the physical memory, or page file.

clive:

I also learned that from the 80386 book that I bought, but it doesn't tell me how to ask Windows for the memory I want.

JoeBtfsplk
Title: Re: Windows Assembly Language Programming
Post by: brethren on February 24, 2011, 11:54:41 PM
if you've installed masm32 then you can allocate a block of memory to use like this
INCLUDE \masm32\include\masm32rt.inc

.data?
pbuf DWORD ?

.code
start:
;allocate 16384 bytes of memory, pbuf contains a pointer
;to the start of the requested memory
mov pbuf, alloc(16384)

;when you've finished with the memory make sure you free it
free(pbuf)

exit
END start
Title: Re: Windows Assembly Language Programming
Post by: jj2007 on February 25, 2011, 12:14:20 AM
Quote from: Joe Btfsplk on February 24, 2011, 10:01:51 PM
it doesn't tell me how to ask Windows for the memory I want.

There are many ways to ask Windows for memory. Here is one - pure Masm:

Quoteinclude \masm32\MasmBasic\MasmBasic.inc (http://www.masm32.com/board/index.php?topic=12460)
   
Init
   Let esi=FileRead$("\Masm32\include\Windows.inc")
   Inkey Left$(esi, 1000)
   
Exit
end start

But seriously, you need a basic intro to the Win32 SDK. Try to get the Windows 32-bit API Help File (http://www.powerbasic.com/support/downloads/Microsoft%20Tools.htm)
Title: Re: Windows Assembly Language Programming
Post by: hutch-- on February 25, 2011, 02:41:31 AM
Joe,

Allocate a GIG of memory. (if you have that much on your machine.)


IF 0  ; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
                            Build this template with "ASSEMBLE AND LINK"
ENDIF ; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

    include \masm32\include\masm32rt.inc

    .code

start:
   
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

    call main
    exit

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

main proc

    LOCAL pMem  :DWORD
    LOCAL gSiz  :DWORD

  ; ------------------------
  ; allocate a GIG of memory
  ; ------------------------
    invoke GlobalAlloc,GMEM_FIXED or GMEM_ZEROINIT,1024*1024*1024
    mov pMem, eax

  ; ------------
  ; get its size
  ; ------------
    invoke GlobalSize,pMem
    mov gSiz, eax

  ; --------------------------
  ; display the allocated size
  ; --------------------------
    fn MessageBox,0,ustr$(gSiz),"This much",MB_OK

  ; ----------------------------
  ; release the allocated memory
  ; ----------------------------
    invoke GlobalFree,pMem

    ret

main endp

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

end start
Title: Re: Windows Assembly Language Programming
Post by: clive on February 25, 2011, 01:52:41 PM
Quote from: Joe Btfsplk on February 24, 2011, 10:01:51 PM
I also learned that from the 80386 book that I bought, but it doesn't tell me how to ask Windows for the memory I want.

Which is why I provided a link to the Win32 API functions most relevant to your question. There are are some extensive books that list functions, but the on-line resource is usually quicker and more up to date.

QuoteCheck the Win32 API functions LocalAlloc(), GlobalAlloc(), HeapAlloc(), VirtualAlloc(), etc
http://msdn.microsoft.com/en-us/library/aa366781%28v=vs.85%29.aspx
Title: Re: Windows Assembly Language Programming
Post by: Joe Btfsplk on February 25, 2011, 08:55:26 PM
Somewhere I heard about a DOS extender?

Is this so that I can use 32 bit instructions in a DOS program? (If it is it would make it a whole lot simpler to convert DOS programs to winows 32 bit because I could test the changes I've made part way through the process of converting a 16 bit DOS program to a 32 bit Windows program. The changes I've made so far compile OK but it crashes when I try to run it.)

If there is a 32 bit DOS extender, how do I get it?

Joe Btfsplk
Title: Re: Windows Assembly Language Programming
Post by: FORTRANS on February 25, 2011, 09:41:31 PM
Quote from: Joe Btfsplk on February 25, 2011, 08:55:26 PM
Somewhere I heard about a DOS extender?

Is this so that I can use 32 bit instructions in a DOS program?

Hi,

   No.  They are for accessing the large amount of memory
that 32-bit modes allow.  You can use 32-bit instructions in
plain DOS.  Use the .386, .486, .586, or .686 directive.  Be
careful, if used wrongly you will be executing instructions that
expect 32-modes in a 16-bit mode, or the opposite.

Quote(If it is it would make it a whole lot simpler to convert DOS programs to winows 32 bit because I could test the changes I've made part way through the process of converting a 16 bit DOS program to a 32 bit Windows program. The changes I've made so far compile OK but it crashes when I try to run it.)

If there is a 32 bit DOS extender, how do I get it?

   Open Watcom C and Fortran comes with a DOS extender.

HTH,

Steve N.
Title: Re: Windows Assembly Language Programming
Post by: hutch-- on February 25, 2011, 11:33:48 PM
Joe,

you can go that way and there are some very good ones around but you then limit your database design to a tiny percentage of computers around the world. What I would suggest is to use your original concept and simply re-write it in 32 bit code so that it is the same to use at the interface level but leverages the Windows API functions and the full 32 bit instruction set.

the Windows API functions look a bit daunting but you can break them down to different families of functions, disk IO, memory allocation strategies, console IO and in the future a GUI interface if and when you need it.
Title: Re: Windows Assembly Language Programming
Post by: clive on February 26, 2011, 12:16:19 AM
There are the DOS4GW, CAUSEWAY and DOS32A DOS Extenders, which work with the Watcom compilers and assembler. There are others more suited to DOS and OS/2 era code, but these aren't free and are more liable not to work well with XP, Vista, Win7, etc. because everyone has moved on, and 1990's era code is not a big priority for everyone today.

Personally I think you be better just skipping that step if you can. You'd have to re-learn the INT 21H interface, ie which registers have expanded to 32-bit, how the segments/selectors work, etc. This is especially true if you are unfamiliar with DPMI. All of which will be completely useless knowledge to gain in 2011.

If you have any familiarity with C, then building a framework in that and working on small 32-bit assembler code fragments might be easier. Or build a small test harness/framework in assembler, and slowly port over basic functions/subroutines from your existing code, assuming you have some layers of abstraction of course.

The big thing you need to get your head around with the Win32 / 386 assembler is that the address space is flat, and you don't want to be using DS/ES/SS/GS/FS etc.

Unless you are writing an OS, the LDT, GDT, TSS and all the other more advance concepts are irrelevant for day-to-day 32-bit coding.

For Win32 API books the following would be worth a look, the latter is broken into functional sections like Hutch describes above.

http://www.amazon.com/Windows-Win32-SuperBible-Other-Sams/dp/1571690891

http://www.amazon.com/Windows-Programming-Complete-programmers-reference/dp/1571690093/ref=pd_sim_b_1
Title: Re: Windows Assembly Language Programming
Post by: MichaelW on February 26, 2011, 04:50:25 AM
Joe,

One problem with 32-bit DOS code, particularly when you are programming in assembler, is that to access the underlying OS you must have a reasonable understanding of the low-level details of both 16-bit real mode code and 32-bit protected mode code. While converting 16-bit DOS code to 32-bit DOS code may be somewhat easier than converting 16-bit DOS code to 32-bit Windows code, with Windows code you are generally insulated from the low-level details of 32-bit protected mode code, and you are targeting the predominate platform.

If I needed a DOS Extender, I would use  Japheth's HX DOS Extender (http://www.japheth.de/HX.html)

Title: Re: Windows Assembly Language Programming
Post by: GregL on February 26, 2011, 08:02:23 PM
Joe,

I agree with the others, forget the DOS Extender.  Go with a port to 32-bit Windows.  Here are some links that may help.

Porting MS-DOS System Calls to the Windows API (http://msdn.microsoft.com/en-us/library/aa984837%28v=vs.71%29.aspx)
Windows API Reference (http://msdn.microsoft.com/en-us/library/aa383749%28v=vs.85%29.aspx)

Good luck with your project.
Title: Re: Windows Assembly Language Programming
Post by: hutch-- on March 02, 2011, 01:31:44 AM
Joe,

Do yourself a favour, instead of "porting" your DOS design to Windows, rewrite it using the design so that you can take advantage of linnear addressing, far faster disk IO and a far more powerful Intel instruction set. You can take advantage of multi-threading and inter-application communication technologies and plonk any of it into a graphics interface where it can be used. Write your own load on call DLLs so that yo can extend the required code base without bloat. Its like shifting from a postage stamp to a football field and you will get a far more powerful result by bothering.

Most of the older guys here came from the DOS and earlier era and we have all had to do the transition from that architecture to a modern protected mode OS architecture but the gains are many and the results when written correctly are massive.
Title: Re: Windows Assembly Language Programming
Post by: Joe Btfsplk on March 03, 2011, 10:24:51 PM
Quote from: hutch-- on March 02, 2011, 01:31:44 AM
Joe,

Do yourself a favour, instead of "porting" your DOS design to Windows, rewrite it using the design so that you can take advantage of linnear addressing, far faster disk IO and a far more powerful Intel instruction set. You can take advantage of multi-threading and inter-application communication technologies and plonk any of it into a graphics interface where it can be used. Write your own load on call DLLs so that yo can extend the required code base without bloat. Its like shifting from a postage stamp to a football field and you will get a far more powerful result by bothering.

Most of the older guys here came from the DOS and earlier era and we have all had to do the transition from that architecture to a modern protected mode OS architecture but the gains are many and the results when written correctly are massive.

Thanks hutch! Now that I'm getting into it! Windows 32 bit doesn't look as daunting as it did before.

When I wrote ADAM around 1986,  I used a little trick to make the parameter passed to ADAM look like a DSECT. (That's mainframe lingo.) ADAM loads the address of the user's parameter into DS which must conform to the Data segment that ADAM has but never uses so it's like a mainframe DSECT. After opening the ADAM file, ADAM gets as much memory as it needs, transfers the data in the user's parameter to the memory it acquired and loads that address into the DS reg. ADAM is then able to address everything as if it were in its data segment.

The same sort of thing should be possible to use in Windows 32 bit. Since ADAM is a far:call for the caller, It should be able to run in the same mode that the caller is in. I shouldn't need to worry about whether ADAM is running in real mode or protected mode. If anyone knows DOS Assembly Language and would like to fool around with ADAM, I'll send you the three .obj modules and some programs that you can use as samples of how to use them. In the meantime, I'm busy on the Windows 32 bit conversion. There should be Windows functions to replace any of the INT instructions that I used in ADAM. I can't see starting over. It works great under DOS and most of it should run under Windows without major modification. Now I just have to find the Windows functions that I need.

Joe Btfsplk
wrmattison@suddenlink.net
Title: Re: Windows Assembly Language Programming
Post by: clive on March 03, 2011, 11:56:34 PM
Realistically you probably only need a dozen or so Win32 API calls to replace the INT21h stuff. Mostly the memory allocation and file stuff I would imagine.

CreateFile, SetFilePointer, ReadData, WriteData, GetFileSize, CloseHandle, and some assorted tricks to get the current file position, or truncate it.

I'll take a look at the DOS OBJs.
Title: Re: Windows Assembly Language Programming
Post by: MichaelW on March 04, 2011, 01:20:46 AM
Quote from: Joe Btfsplk on March 03, 2011, 10:24:51 PM
The same sort of thing should be possible to use in Windows 32 bit. Since ADAM is a far:call for the caller, It should be able to run in the same mode that the caller is in. I shouldn't need to worry about whether ADAM is running in real mode or protected mode.

Beyond the problem with software interrupts, if ADAM was assembled/compiled as 16-bit real mode code it will not run in protected mode without modification.

QuoteI can't see starting over.

I can see why you would not want to start over on the algorithm, file format, etc design, but why not start over on the code design? You already need to change the OS interface and change from 16-bit near or far addressing to 32-bit near addressing. Why not redesign the code to take full advantage of the 32-bit address space, 32-bit instructions, and the much larger memory capacities of today?

Title: Re: Windows Assembly Language Programming
Post by: dedndave on March 04, 2011, 10:54:34 AM
noone is more resistant to change than i am, Joe - lol
i wrote 16-bit asm code for years
a couple years ago, i decided to bite the bullet and dig into win32
there is a lot of material to cover for GUI apps - but it's not that bad
it isn't bad at all if you want to write 32-bit console apps