News:

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

Converting old asm to masm32

Started by Spudster, December 17, 2008, 12:02:39 AM

Previous topic - Next topic

Spudster

I ordered Peter Norton's Assembly Language Book for the IBM PC (1989) and have found it very helpful to learn how the processor works (hey, it was only $0.50), and how to use individual opcodes to run small programs using a 32bit version of Debug for DOS.  Also I've been able to save these out as a .com file and run those just fine.  Now I need to start writing my own assembly programs, and compiling them to executables.  Here is some example code from the book:

.MODEL SMALL
.CODE
  MOV AH,2h
  MOV DL,2Ah
  INT 21h
  INT 20h
  END


And I was wondering how I might learn how this translates into today's MASM32 language, or if it's even worth it.  I've tried to translate this code into the following:

.386
.model flat, stdcall
option casemap :none

.code
main:
mov ah,2h
mov dl,2ah
int 21h
int 20h
end main


but this isn't working for me either.  It assembles and links just fine, but when I go to run the executable it crashes.  Maybe it's just that I don't understand enough of how executables work, or the language in general.  I guess a lot of this is me putting myself through grief.  I want to be able to write a small program without using the Windows API packages that came with MASM32.  I've been trying to understand what are the individual commands that Windows uses to do things like ExitProcess, etc.  Probably just trying to run before I can crawl.

So, if anyone could show me an example program that could even just exit properly, without crashing, and without using any Windows API that would be very appreciated.  Or maybe explain how I could extract information like this from the different libraries available, I could use that to find the answers to any future question I may have.  Thanks.

redskull

To speak in broad generalities, any time you see him MOV parameters into registers and then make an INT call, the Windows equivilent is to PUSH the parameters on the stack and do a CALL to the appropriate function.  For example, INT-21/2 with dl as '*' is to display a character on the screen; the equivlent Windows version would be to do either a MessageBox() function for a window or a WriteConsole() function for a command-style box with the appropriate paramters.  INT-20 is to exit the program, which in Windows would be a call to ExitProcess().  Granted it's far more involved than that, but it should get you started.  You can't, however, avoid using the Windows functions if you want to write Windows programs.  BTW, I learned assembly from the same book (still the best). 

-alan
Strange women, lying in ponds, distributing swords, is no basis for a system of government

Spudster

Oh, I see.  So even using INT was in essence calling a windows function.  Hm.  Okay.

Thanks for the info.  I see now that I'm trying to understand concepts of OS design without first learning the language.  I've been studying this every spare moment I've had for the last few weeks, and so far a big part of the battle for me has been just been figuring out what to use.  I'm really bothered by all my professors telling me that it's ridiculous to want to learn in depth assembly.  It's powerful, fast and allows some great advantages.  My ultimate goal is to write my own small OS, but I know that is a bit out there.  Time to focus on the basics.

Farabi

Quote from: Spudster on December 17, 2008, 02:15:53 AM
Oh, I see.  So even using INT was in essence calling a windows function.  Hm.  Okay.

Thanks for the info.  I see now that I'm trying to understand concepts of OS design without first learning the language.  I've been studying this every spare moment I've had for the last few weeks, and so far a big part of the battle for me has been just been figuring out what to use.  I'm really bothered by all my professors telling me that it's ridiculous to want to learn in depth assembly.  It's powerful, fast and allows some great advantages.  My ultimate goal is to write my own small OS, but I know that is a bit out there.  Time to focus on the basics.
If you want to write a small OS, have you check on FASM website? They got a good open source OS.
Those who had universe knowledges can control the world by a micro processor.
http://www.wix.com/farabio/firstpage

"Etos siperi elegi"

GregL

#4
QuoteOh, I see.  So even using INT was in essence calling a windows function.  Hm.  Okay.

No, DOS interrupts do not call Windows functions.

DOS interrupts will not work in a Windows application. If you want to learn assembly language for Windows, that book is not going to do you any good.

[edit]
If you want to write DOS apps, you've got a good book. I had that book years ago.


japheth

Quote from: Spudster on December 17, 2008, 12:02:39 AM
I've tried to translate this code into the following:

.386
.model flat, stdcall
option casemap :none

.code
main:
mov ah,2h
mov dl,2ah
int 21h
int 20h
end main


but this isn't working for me either.  It assembles and links just fine, but when I go to run the executable it crashes.  Maybe it's just that I don't understand enough of how executables work, or the language in general.  I guess a lot of this is me putting myself through grief.  I want to be able to write a small program without using the Windows API packages that came with MASM32.

To code 32bit in DOS without using the Win32 API is simple, the prefered and simplest way to do so is to use DPMI. In the JWasm package there are some very basic examples (Dos2.asm for 16bit protected-mode, Dos3.asm for 32bit protected-mode). Your sample code above, which uses the FLAT memory model, requires a PE program loader, which is kind of advanced topic as far as DPMI is concerned, but still no problem if you are a bit experienced.

Anyways, you're absolutely right to ignore the Windows API. Windows programming is boring and lame, DOS programming is fun. Congratulations!



UncleHenry

Quote from: Spudster on December 17, 2008, 02:15:53 AM
Oh, I see.  So even using INT was in essence calling a windows function.  Hm.  Okay.

Quote from: Spudster on December 17, 2008, 02:15:53 AM
Oh, I see.  So even using INT was in essence calling a windows function.  Hm.  Okay.
es.  My ultimate goal is to write my own small OS, but I know that is a bit out there.  Time to focus on the basics.

DOS executes in real mode, where the INT n instruction just transfers control to the code whose address is stored in the interrupt table "nth" entry.

The entries in the interrupt table are also used to handle hardware interrupts: when one such interrupt occurs, the interrupt controller tells the processor to transfer control to the address stored into the "nth" table entry. Thise means that, in DOS, you could invoke hardware interrupt handlers with the INT instruction, emulating the occurrence of an hardware interrupt.

Windows goes at great lenghts to forbid your code to do such a thing, because hardware interrupt handlers are part of the kernel or of device drivers and application code must not invoke them directly.

It is one thing to fiddle with the hardware in a single task OS like DOS and an entirely different game to do it in an OS where multiple programs run at the same time. If they could toy with hardware devices as if they owned the machine very bad things could happen.

It is possible to avoid this, because in Windows the processor executes in protected mode, where different pieces of code have different privilege levels and application code is the least privileged.

The data structure referenced by the INT instruction in protected mode is configured so that code running at lower privilege cannot issue the instruction. If your code tries to execute an INT, the processor generates a fault; this means your instruction is not executed and control is immediately transferred to a fault handler (as if an hardware interrupt has occurred). The handler is part of the operating system and mercilessly terminates your process because of its misbehaving.

So an INT is not a call to a Windows API at all, it's a special instruction whose use is forbidden. A real call to a windows API is a plain CALL instruction to the appropriate routine address.

If you are interested in OS architectures, you could find the x86 protected mode a very interesting subject. It's explained in great detail in:

Intel 64 and IA-32 Architectures
Software Developer's Manual; Volume 3A:
System Programming Guide, Part 1

which is available for free on the intel site.

Spudster

Hey everyone.  Thanks for all the input.  I have a lot to look over for the next little while.  After having tried learning all this on my own I wanted to break my laptop in half, but thankfully all your input has saved it.  Assembly seems like such a slick and powerful way to program the computer, and honestly after learning MASM, going back to C++ seems almost trivial.  It bothers me that so many people think it's ridiculous that I'm putting so many hours in to learning this.  I'm glad to see that there are others out there like me.

japheth

Quote from: Greg on December 17, 2008, 03:40:27 AM
DOS interrupts will not work in a Windows application.

This is nonsense of course. However, you'll read this claim very often here, which might tell something about the level of knowledge in this forum ...  :green

As a simple proof see this little application which calls DOS interrupts and which runs fine as a Win32 process:


;--- running DOS in Win32

        .386
        .MODEL FLAT, stdcall
        option casemap:none

        include \masm32\include\windows.inc
        include \masm32\include\kernel32.inc
       
        includelib \masm32\lib\kernel32.lib

        .data

szHello db "Hello world!",13,10,'$'

        .code

main    proc c

        mov edx,offset szHello
        mov ah,09h
        int 21h
        mov ax,4c00h
        int 21h
       
main    endp


myexc proc c uses ebx esi edi pReport:dword, pFrame:dword, pContext:dword

        mov ebx, pReport
        mov edi, pContext
        mov edx, [edi].CONTEXT.regEip
        .if (word ptr [edx] == 021CDh)
            mov al,byte ptr [edi].CONTEXT.regEax+1
            .if (al == 09)
                invoke GetStdHandle, STD_OUTPUT_HANDLE
                mov ebx, eax
                mov esi,[edi].CONTEXT.regEdx
                .while (byte ptr [esi] != '$')
                    push 0
                    mov edx, esp
                    invoke WriteConsole, ebx, esi, 1, edx, 0
                    pop edx
                    inc esi
                .endw
                and byte ptr [edi].CONTEXT.regFlag,0FEh
            .elseif (al == 4Ch)
                movzx eax,byte ptr [edi].CONTEXT.regEax
                invoke ExitProcess, eax
            .endif
            add [edi].CONTEXT.regEip, 2
            mov eax,0 ;0=continue execution
        .else
            mov eax,1
        .endif
        ret
myexc endp

mainCRTStartup proc c

        assume fs:nothing

        xor edx,edx
        push offset myexc
        push fs:[0]
        mov fs:[edx],esp
        call main
        invoke ExitProcess, eax

mainCRTStartup endp

        END mainCRTStartup




Spudster

Wow. Nice code japheth.  I got it to assemble and run just fine.  Unfortunately I don't understand most of it.  Though I understand now that I was combining assembly commands and system resource calls (excuse my incorrect usage of these terms; I'll try to explain ), or in other words commands like mov, add, etc. and other commands that call on resources provided by the operating system (e.g. ExitProcess).  What I had figured was that even commands used by the operating system also had to be broken down into simple commands such as mov, etc.  While I am curious if it would be possible to extract the exact "simple instructions" used by the operating system, then implement those directly into the code so that it wouldn't need to link to any .inc or .lib files, I can wait until I understand the language better.

So my million dollar question is then, how did you learn how to do that?  I've been all over the web looking for resources and while I've found plenty of explanations of aspects in assembly, I've never been able to find a comprehensive guide that I could sit down with and read straight through.  There's always a problem getting a program to assemble correctly, or that it wasn't even written for MASM syntax.  What resources did all of you use to learn what you know?  Hell or high water come, I'm going to learn this, but life would be a lot more pleasant if I found some more straight forward resources.  What I would really like to program for is the Win32 console.  I like the feeling of the console more, and really I'm more interested in versatility then good looks.  Any ideas?

hutch--

Japheth is pulling your leg here, the code is a dos stub that runs in the DOS subsystem, it is not win32 code and will not run under win32. T4ry and run dos int 21h or int 10h calls in a win32 PE application and it will go bang on you, very early versions of win95 still supported a few interrupts but none of the NT based OS version do.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

japheth

Quote from: hutch-- on December 18, 2008, 10:31:37 AM
Japheth is pulling your leg here, the code is a dos stub that runs in the DOS subsystem, it is not win32 code and will not run under win32. T4ry and run dos int 21h or int 10h calls in a win32 PE application and it will go bang on you, very early versions of win95 still supported a few interrupts but none of the NT based OS version do.

Dear Hutch, let me give you some hints in friendship:

1. delete your last post as quickly as possible, because it might damage your reputation.
2. try to read the posts carefully before replying. I clearly told that my little sample runs as a true Win32 process, not in the "DOS subsystem". It definitely is Win32 code, and the code doesn't use any "dirty" tricks.

UncleHenry

Hutch is absolutely right. Japheth's code uses a Windows facility called Structured Exception Handling (SEH), which allow a program to be notified when it has generated a fault. The INT 21h does indeed generate the fault I explained earlier, so that execution jumps into the fault handler, which is part of the OS. With SEH you tell the OS handler "call me back if I've done something wrong". So, the OS, instead of terminating your process calls you back at the address you supplied to SEH. In Japheth's code, control is transferred to the myexc functions, which emulates the DOS function for writing output to the console by calling WriteConsole(), which is a Windows API function.

So basically, what this program does is:
- installs an exception handler
- pretends to execute an int 21h to write to the console, when this is not allowed by windows
- regains execution at its exception handler where the int 21h functionality is emulated by calling Windows API functions

Why would anyone want to write such nonsense, instead of simply calling WriteConsole() is anybody's guess.

ecube

Quote from: japheth on December 18, 2008, 10:54:33 AM
Quote from: hutch-- on December 18, 2008, 10:31:37 AM
Japheth is pulling your leg here, the code is a dos stub that runs in the DOS subsystem, it is not win32 code and will not run under win32. T4ry and run dos int 21h or int 10h calls in a win32 PE application and it will go bang on you, very early versions of win95 still supported a few interrupts but none of the NT based OS version do.

Dear Hutch, let me give you some hints in friendship:

1. delete your last post as quickly as possible, because it might damage your reputation.
2. try to read the posts carefully before replying. I clearly told that my little sample runs as a true Win32 process, not in the "DOS subsystem". It definitely is Win32 code, and the code doesn't use any "dirty" tricks.


Speaking to hutch in this manner is completely inappropiate and unappreciated. There are proper ways to respond to things and theres improper ways, and you definitely chose the latter

hutch--

Cube,

Its only humour.  :bg

>1. delete your last post as quickly as possible, because it might damage your reputation.

Telling the truth is in fact dangerous, we do it all the time here.

None the less the simple SEH example is worth understanding.

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