News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Convert 16-bit MASM program to 32 bits?

Started by Futurepower(R), December 11, 2010, 11:17:44 AM

Previous topic - Next topic

Futurepower(R)

How do I convert 16-bit Microsoft MASM programs to 32-bit Microsoft MASM? The program below is an example. I know how to convert to 32-bit registers. I don't know what assembler flags to use, or what code structure is necessary. Microsoft has dropped 16-bit program support from its 64-bit operating systems.

        Name RemCRLF
        Title   Remove carriage return, line feed, and end-of-file characters. (CR, LF, and EOF)
        page    ,132
comment /

        RemCRLF.com is a filter that deletes CR, LF, and DOS EOF (1Ah)
        characters from a file.

        Examples:

        RemCRLF   abc.txt   Read input from abc.txt, output to the screen.
        RemCRLF   abc.txt > abcnew.txt
        RemCRLF < abc.txt > abcnew.txt
        RemCRLF   abc.txt | find "ABC"

        Find "abc" abc.txt | RemCRLF | sort

/

; D:\Asm_Lang\BorlandC\BIN\tasm.exe /C /LA /W2 /X /Z %1.asm %1.obj %1 %1
; TLink options must be lower case, except when specified below, apparently.
; D:\Asm_Lang\BorlandC\BIN\tlink.exe /m /s %1
; D:\Asm_Lang\Asm\EXE2BIN.EXE %1.EXE %1.COM

;===================================================================
code    segment public
;===================================================================
;
;       command line is at 80h of psp - first byte is length
;
        org     80h
parmsize        db      ?
parm            db      7fh dup (?)
;
; .com starts at 100h - but must jump around any data area
;
        org     100h                    ; com file starts here
        assume  cs:code,ds:code,es:code
RemCRLF:
        jmp     clear
;===================================================================
;
; data area for .com programs
;
cr      equ     0dh
lf      equ     0ah
eof     equ     1ah
;
handle  dw      0h                      ; assume standard input
bufsiz  equ     255
bufferin        db      bufsiz dup (?)
bufferout       db      bufsiz dup (?)
flag            db      0h
outcount        dw      0h              ; output char count
;
;===================================================================
clear:
;
; start of actual code is here (clear:)
;
;
; now figure out which file to read from - parm line or standard input
;
        cmp     parmsize,0h     ; if zero, no parm
        jz      again           ; assume standard input
;
; parm length is not zero - assume the parm is a file name.  If not
; found, quit.
;
        mov     al,parmsize     ; get size of parm
        xor     ah,ah           ; zero out top part of accum.
        mov     si,ax           ; use length as a pointer into the dta
        mov     [si]+parm,0h    ; to tack on a zero byte (asciiz).
;
; now try to open the file
;
        lea     dx,parm+1       ; address of 'filename'
        mov     al,0h           ; open for read only
        mov     ah,3dh          ; dos open function
        int     21h             ; invoke function
        jc      oops            ; open error - quit
        mov     handle,ax       ; save file handle
again:
        mov     bx,handle       ; read from standard input or file
        mov     cx,bufsiz       ; # of characters to read
        lea     dx,bufferin     ; seg:off address of buffer area
        mov     ah,3fh          ; dos read function
        int     21h             ; invoke function
;
        jc      oops            ; error!
        cmp     ax,0h           ; if zero, end of file
        jz      oops
;
        mov     cx,ax           ; cx (and ax) contain # characters read
        mov     outcount,0h     ; init output character counter
        lea     si,bufferin     ; offset of buffer
        lea     di,bufferout    ; address of output area
loop1:
        lodsb                   ; Get a character.
        cmp     al,cr           ; If Carriage Return character, skip.
        je      skip
        cmp     al,lf           ; If Line Feed character, skip.
        je      skip
        cmp     al,eof          ; If DOS EOF (End Of File) character, skip.
        je      skip
;
; Not CR, LF, or EOF character, add to the output buffer:
        inc     outcount        ; increment count of characters output
        stosb
skip:
        loop    loop1           ; and repeat for entire buffer
;
        mov     cx,outcount     ; restore character count
        mov     bx,1h           ; standard output device
        lea     dx,bufferout    ; output buffer
        mov     ah,40h          ; dos write function
        int     21h             ; invoke dos function

        jmp     again           ; repeat until end of file or error
oops:
        int     20h             ; return to dos
code    ends
        end     RemCRLF

hutch--

Do yourself a favour, write a new 32 bit algo. Converting a pile of old DOS junk is a waste of time. My suggestion is to use a 256 char lookup table and exclude those characters. You would probably replace CR and LF (13,10) combinations with a single space.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

Futurepower(R)

I don't know how to write a 32-bit assembly language console program, because I don't know the structure. It would be good to have any console program as a model.

In this case, I need to use Microsoft's MASM.

donkey

You can use the search function to look for "console", that will probably yield quite a few example apps for the console.
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

Magnum

There are console examples in this directory.



C:\masm32\examples\exampl07\console
Have a great day,
                         Andy

hutch--

> I don't know how to write a 32-bit assembly language console program, because I don't know the structure.

Looks like you have some learning to do. The task is simple enough but you must know how to write code like this. Show us your efforts in writing a 32 bit algo and we may be able to help you get it going.

Here is a small test piece that does some of your task, it removes CRLF pairs and replaces them with a space. I have left the space for you to do the characters substitutions yourself.


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

    include \masm32\include\masm32rt.inc

    textclean PROTO :DWORD

    .code

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

    call main
    inkey
    exit

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

main proc

    LOCAL pMem :DWORD

    mov pMem, InputFile("tclean.asm")

    invoke textclean,pMem

    print pMem

    ret

main endp

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

textclean proc ptxt:DWORD

    push ebx
    push esi
    push edi

    mov esi, ptxt
    mov edi, ptxt
    sub esi, 1

  mainloop:
    add esi, 1
    movzx eax, BYTE PTR [esi]
    test eax, eax                           ; exit on zero
    jz quit
    cmp eax, 13                             ; branch to subloop on CR
    je subloop
    cmp eax, 10                             ; branch to subloop on LF
    je subloop
  ; -----------------------------------
  ; do the character substitutions here
  ; -----------------------------------



  ; -----------------------------------
    mov [edi], al                           ; write each normal byte
    add edi, 1
    jmp mainloop

  subloop:
    add esi, 1
    movzx eax, BYTE PTR [esi]
    test eax, eax                           ; exit on zero
    jz quit
    cmp eax, 13                             ; loop back on CR
    je subloop
    cmp eax, 10                             ; loop back on LF
    je subloop
    mov BYTE PTR [edi], 32                  ; write space
    add edi, 1
    jmp mainloop

  quit:
    mov BYTE PTR [edi], 0                   ; write terminator

    pop edi
    pop esi
    pop ebx

    ret

textclean endp

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

end start
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

Futurepower(R)

Hutch,

Thank you for the code sample. It is very much appreciated.

I do have a real need to convert 16-bit assembly language programs to 32-bits. Some of what I have is so long that it would take a long time to re-write it. Do you know of any information about how to do that?

Can I still call interrupts like this, even though I am using Windows XP 32-bits, or Windows 7 64-bits?

        mov     bx,handle       ; read from standard input or file
        mov     cx,bufsiz       ; # of characters to read
        lea     dx,bufferin     ; seg:off address of buffer area
        mov     ah,3fh          ; dos read function
        int     21h             ; invoke function

What assembler flags would I use? I have been able to convert the code I posted previously so that it assembles and links without error, but it crashes immediately when I try to run it. I think that it because I don't know the MASM statement to designate the entry point.

donkey

Hi,

You can't use interrupts, they are not used in protected mode applications. Instead you will have to use the Windows API. The console functions and Windows API string functions will provide you with most of what you need to mimic a DOS application in 32 bit.

For example:

.686p
.model flat, stdcall  ;32 bit memory model
option casemap :none  ;case sensitive

include Windows.inc
include Kernel32.inc
includelib Kernel32.lib

.data
    hStd dd 0
    szString db "Hello World",0
    pString dd OFFSET szString
    cbWrite dd 0

.code
Start:

    invoke GetStdHandle,STD_OUTPUT_HANDLE
    mov hStd, eax
    invoke lstrlenA,pString
    mov ecx,eax
    invoke WriteFile,hStd,pString,ecx,ADDR cbWrite,0
    invoke CloseHandle,hStd
    invoke ExitProcess,0

End Start


In the code above, the FLAT model specifies 32 bit code with no segments selectors. The data section and code section are separate, this is important for any newer Windows with DEP enabled since executing code in the data section is usually verbotten, they should be kept separate anyway, its just good practice.

Start: in the code section is the label that indicates your entry point, it is matched by End Start at the end of the code, setting up this pair tells MASM where to set the entry point. GetStdHandle retrieves the standard output handle for the console, you use this handle with WriteFile to output text to the screen, in this case "Hello World". After that you close the handle and call ExitProcess to shut your program down.

As you can see all of the non-GUI Windows API is available to you as well as the C runtime library (through msvcrt.dll). The only thing that you can't do in a console application is set up a message pump, which means no windowed applications (yes there are tricks but that's beyond your needs and abilities right now). In the case of your first post, most of the functionality can be achieved through calls to the Kernel32 library, it includes many parsing and string manipulation functions.

For now I would search both the internet and this board for examples of how to achieve particular tasks in the console. For example how to get input from the console (ReadFile/ReadConsole).

Edgar
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

jj2007

Hi. To my knowledge, there aren't any automatic converters from 16- to 32-bit assembly around, although it would be a cute idea.

32-bit assembler is a lot easier than 16-bit assembler, but conversion will be tricky. You would have to be proficient in both worlds to write a converter, and say byebye to interrupts. There are simple macros that can replace them.

If you still understand what the old code did, what stops you from using a high level language like C or Basic? Speed should be much less of a problem than at the time your code was written...

As to the structure, here is a template that may illustrate what you really need. Use "Console assembly and link". I typed this up in parallel to Edgar's example, so here you have something slightly different for comparison.

include \masm32\include\masm32rt.inc

MyTest PROTO:DWORD,:DWORD

.data
AppName db "Masm32: ", 0

.data?
MyBuffer db 128 dup(?)

.code
start:
print "Hello World! Type a line and press Enter:", 13, 10
invoke StdIn, offset MyBuffer, sizeof MyBuffer
invoke MyTest, offset AppName, chr$("so easy", 13, 10)
invoke MyTest, chr$("This is the line you entered:", 13, 10), offset MyBuffer
exit

MyTest proc arg1, arg2
 print arg1
 print arg2
 ret
MyTest endp

end start

MichaelW

You also cannot use 16-bit addressing in a 32-bit Windows application. So in addition to converting the code that does interrupt calls, you will need to convert the code that deals with memory buffers.
eschew obfuscation

dedndave

i would think you could write a set of 32-bit routines that behave similarly to the 16-bit interrupts
so, that part of an "automated" conversion might not be all that difficult
however, whenever a 16-bit program re-vectors an interrupt, a 32-bit convertor would be lost

but, the real (pun) problem lies with the difference in the way 16-bit and 32-bit programs access memory
an automated conversion program would have to use some smarts to figure out the intent of the programmer, i think

another issue is the fact that 16-bit programs had free reign over memory and I/O
in 32-bit, these resources are protected
this issue could be probably be overcome

in the end, i think it is a waste of time - lol
emulating the 16-bit world would be much simpler than auto-converting the code
this is what NTVDM does for you under MS 32-bit OS's

if you are in a business situation where some old 16-bit software provides required solutions, i might be inclined to take a 2-step approach:

1) for short-term, use something like DOSBox to run the old code
this may get you up and running while you apply step 2 - it buys you time to learn 32-bit code

2) work toward totally replacing each 16-bit program with a 32-bit solution
you can probably do this on a one-by-one basis
in some cases, you may be able to find an existing 32-bit program that does what you need to do
in other cases, you may have to write some code   :P

another approach would be to hire a programmer to write the replacement code
we don't know what you need - so i can't say if this is cost-effective
if you have one or two not-so-complicated applications, this might not be too bad of an idea