Author Topic: How do I make an EXE?  (Read 19470 times)

Offline ben321

  • Full Member
  • **
  • Posts: 182
How do I make an EXE?
« on: March 20, 2015, 07:43:54 AM »
I'm using NASM in Windows. The only executable format that NASM can output are either raw binary code, or a ".o" object file which is apparently an "elf" format file. It can't export an EXE file. How do I convert either raw binary code into an EXE or a .o file into an EXE file?

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: How do I make an EXE?
« Reply #1 on: March 20, 2015, 04:42:19 PM »
Quote
The only executable format that NASM can output are either raw binary code, or a ".o" object file which is apparently an "elf" format file.

I'm not sure where you found this misinformation.
Code: [Select]
nasm -hf
will give you a list of the output formats that Nasm will produce. As you can see, there are quite a few of them. Most suitable for Windows would be "-f win32" (alias "-f win") or "-f win64". These do not, in themselves, produce an .exe -  you will require the assistance of a suitable linker - "golink" seems most popular recently, but there are others.

"-f obj" will also produce an object file which can be linked into a Windows .exe, but it defaults to 16-bit code and you'll need to specify "use32" on each and every segment you define. I consider it an "obsolete" format, and would use it only if you're stuck with a linker that demands this format (Borland?). Better to get yourself a modern linker, IMO.

Nasm will - all by itself, no linker - also produce an .exe from the flat binary "-f bin" format, but you'd have to create an executable header "by hand" (there are macros available to ease this chore). This would be less flexible, since you'd be stuck with a single module, but it does work.

I'd advise you to stick with "-f win32" or "-f win64". The "elf" formats are for when you graduate from  Windows.

Best,
Frank


Offline ben321

  • Full Member
  • **
  • Posts: 182
Re: How do I make an EXE?
« Reply #2 on: March 20, 2015, 06:09:12 PM »
Quote
The only executable format that NASM can output are either raw binary code, or a ".o" object file which is apparently an "elf" format file.

I'm not sure where you found this misinformation.
Code: [Select]
nasm -hf
will give you a list of the output formats that Nasm will produce. As you can see, there are quite a few of them. Most suitable for Windows would be "-f win32" (alias "-f win") or "-f win64". These do not, in themselves, produce an .exe -  you will require the assistance of a suitable linker - "golink" seems most popular recently, but there are others.

"-f obj" will also produce an object file which can be linked into a Windows .exe, but it defaults to 16-bit code and you'll need to specify "use32" on each and every segment you define. I consider it an "obsolete" format, and would use it only if you're stuck with a linker that demands this format (Borland?). Better to get yourself a modern linker, IMO.

Nasm will - all by itself, no linker - also produce an .exe from the flat binary "-f bin" format, but you'd have to create an executable header "by hand" (there are macros available to ease this chore). This would be less flexible, since you'd be stuck with a single module, but it does work.

I'd advise you to stick with "-f win32" or "-f win64". The "elf" formats are for when you graduate from  Windows.

Best,
Frank

Thanks for the info. From other things I've read, it also appears that -f Obj is needed to get around a certain bug in NASM which prevents the use of the "import" directive when using -f Win32. Importing is absolutely essential for 99% of programs you are going to write, as it is needed to gain access to Windows API functions like MessageBoxA (which are found in DLL files in the Windows\System32 folder) so that they can be called later with the "call" op code (in the case of MessageBoxA, this spawns a message box). So using -f Win32 (for now, until this bug is fixed) is only useful for a few VERY SIMPLE programs that require ABSOLUTELY NO DLLs, and such simple programs are only good for "getting the hang of" programming in assembly. I plan to write a separate post on the forums here regarding this, as a bug-report, so hopefully the guy who writes this assembler can get around to fixing the bug.

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: How do I make an EXE?
« Reply #3 on: March 20, 2015, 07:04:52 PM »
I suspect you'll wait a long time for that "bug" to be fixed. The "import" directive (like "..start") exists in the "-f obj" format, but not in "-f win32", simple as that.

I personally wouldn't use Windows if my life depended on it, but I've heard rumors that people do use it successfully. You might get better results if you asked how to do so, rather than telling us what we're doing wrong. Just a thought...

Best,
Frank


Offline ben321

  • Full Member
  • **
  • Posts: 182
Re: How do I make an EXE?
« Reply #4 on: March 20, 2015, 08:02:18 PM »
It's a bug with Import because there's no alternative in Win32. With ..start: there is an alternative for Win32 mode. Simply define the label you want like GLOBAL MAIN in your source code, place the label MAIN: where you want the program to start in your source code, and then compile. Then when linking, simply use the command line "alink.exe -oPE -entry MAIN myprogram.obj". It will use the user-defined label MAIN for the entry point.

With Import there is no alternative for using in Win32 mode. Win32 mode is the only proper way to compile for Windows using NASM. Are you starting to see the problem here? Using Obj mode when compiling for Windows is simply a hack. Obj mode was intended for DOS only. One of the basic rules for a programmer is not to depend on hacks to make your code work. Hacks are not dependable. There is no guarantee that they will continue to work in a future version of the assembler. So one of the basic rules for the writers of assemblers is not to force programmers who are using your assembler to depend on hacks.


And this is how I know that it is a bug to have Import working only in Obj mode, and that Obj mode was NEVER intended for Windows use. When you load a program into OllyDbg to debug/test it, if it was compiled in Win32 mode you get no error messages. However, if you load one that was compiled in Obj mode, though you will be able to debug it and test it, you will also get this error message:


Because of this, there is no way of knowing that your suggested workaround for the Import problem, of using Obj mode, will in fact produce stable code. It might very well introduce bugs into your program once you start making more complicated software.
« Last Edit: March 20, 2015, 08:45:21 PM by ben321 »

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: How do I make an EXE?
« Reply #5 on: March 20, 2015, 09:25:36 PM »
Thanks for explaining that to us, ben123! Apparently the folks who have been creating Windows executables for years have been fooling themselves. We would never have figured that out if you hadn't showed up! :)

Code: [Select]
alink.exe -oPE -entry MAIN myprogram.obj win32.lib
may fix you up...

Don't have such an import library? (Doesn't Alink come with one?) I have not done this, but I am told you can create your own by using "-f obj" and the "import" directive for the .dlls you want - nothing else. Assemble this as "-f obj", and the resulting .obj can allegedly be linked with "-f win32" objects. I do not vouch for this.

My understanding is that if you use Golink, you can simply add the .dlls you need to the end of the command line. It also has support for "-f win64". Alink should still work, but as you probably know, Anthony is no longer maintaining it.

I think you'll get a more harmonious outcome if you ask for help with the parts you don't understand, rather than telling us what we're doing wrong.

C'mon you Windows guys, tell this poor confused beginner how to do it. Pretend he asked politely.

Best,
Frank


Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: How do I make an EXE?
« Reply #6 on: March 20, 2015, 09:57:57 PM »
Since you changed your previous post since I last read it, let me make this suggestion:
Code: [Select]
section code use32 class=CODE
That may pacify Ollydbg. No promises, it's been a long, long time...

I really think you'd be better off to learn how to use the more modern "-f win32". People do it, honest!

Best,
Frank


Offline ben321

  • Full Member
  • **
  • Posts: 182
Re: How do I make an EXE?
« Reply #7 on: March 20, 2015, 10:20:14 PM »
Thanks for explaining that to us, ben123! Apparently the folks who have been creating Windows executables for years have been fooling themselves. We would never have figured that out if you hadn't showed up! :)

Code: [Select]
alink.exe -oPE -entry MAIN myprogram.obj win32.lib
may fix you up...

Don't have such an import library? (Doesn't Alink come with one?) I have not done this, but I am told you can create your own by using "-f obj" and the "import" directive for the .dlls you want - nothing else. Assemble this as "-f obj", and the resulting .obj can allegedly be linked with "-f win32" objects. I do not vouch for this.

My understanding is that if you use Golink, you can simply add the .dlls you need to the end of the command line. It also has support for "-f win64". Alink should still work, but as you probably know, Anthony is no longer maintaining it.

I think you'll get a more harmonious outcome if you ask for help with the parts you don't understand, rather than telling us what we're doing wrong.

C'mon you Windows guys, tell this poor confused beginner how to do it. Pretend he asked politely.

Best,
Frank


AWESOME! That's what I needed! That win32.lib really worked. Here's the source code to my test program that uses it.

test.asm
Code: [Select]
EXTERN MessageBoxA
EXTERN ExitProcess


SEGMENT .text
GLOBAL main

title db "My Title",0
message db "This is a test.",0

main:
push dword 0
push dword title
push dword message
push dword 0
call MessageBoxA

push dword 0
call ExitProcess

Note that the "dword" keyword may be redundant, as Stack entries in win32 are by default 32 bit entries, but I got some of this code off of another site that had a sample program, and it had the "dword" keywords in there (though it appeared to be using "-f obj" in the compiler command which is 16 bit by default so "dword" may not have been redundant for their example). So I kept it in there, just in case it was needed. If it isn't needed in my case, hopefully somebody here will be able to let me know.


Here are the command lines I used for compiling and linking.

Compile command line:
Code: [Select]
nasm -f win32 test.asm
Link command line:
Code: [Select]
alink -oPE -entry main test.obj win32.lib
It now works as intended.


Again, a BIG thanks to you for suggesting using win32.lib.
« Last Edit: March 20, 2015, 10:38:03 PM by ben321 »

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: How do I make an EXE?
« Reply #8 on: March 20, 2015, 10:54:21 PM »
There ya go! Thanks for the working example - we have too few of them.

Regarding the "dword" size specifier - Nasm will let you know if it needs it and doesn't see it. As I recall, "push 0" used to need it, but it was concluded that it was reasonable to make the "current bitness" the default for immediates, so you shouldn't need it now. Nasm "knows" how big the labels are, so you shouldn't need it. "push dword [myvar]" would still need it. It does no harm to use it, and may make your code clearer.

Best,
Frank


Offline ben321

  • Full Member
  • **
  • Posts: 182
Re: How do I make an EXE?
« Reply #9 on: March 21, 2015, 12:38:22 AM »
By the way, which is the more proper way to end a program?
Should I use the "ExitProcess" API function? Or should I use the assembly opcode "ret"?

I've noticed ret seems to work, as it returns the program's flow back to the calling code. Yes, running an EXE file actually is in fact actually Windows calling your EXE file in the same way your EXE file can call a function in a DLL file (or a subroutine in your own program), because when running it in OllyDbg, you can see that just before the excution pointer is in your EXE's, it is in fact executing in ntdll which is part of Windows. By using "ret" it exits your program and returns the code pointer back to ntdll in the same way that you can exit a sub routine. As far as Windows is concerned, your program is just a sub routine in Windows.

But does using "ret" leave some things in a "not cleaned up" state, things that WOULD be cleaned up if you ran the ExitProcess function?



Also, which is the more correct way of marking the executable code section of your assembly code? Is it better to use "SEGMENT .text" or SEGMENT .code"? I've seen some examples that use the ".text" version of this line, and some that use the ".code" version of this line.
« Last Edit: March 21, 2015, 12:39:56 AM by ben321 »

Offline Bryant Keller

  • Forum Moderator
  • Full Member
  • *****
  • Posts: 360
  • Country: us
    • About Bryant Keller
Re: How do I make an EXE?
« Reply #10 on: March 29, 2015, 01:45:42 AM »
By the way, which is the more proper way to end a program?
Should I use the "ExitProcess" API function? Or should I use the assembly opcode "ret"?

I've noticed ret seems to work, as it returns the program's flow back to the calling code. Yes, running an EXE file actually is in fact actually Windows calling your EXE file in the same way your EXE file can call a function in a DLL file (or a subroutine in your own program), because when running it in OllyDbg, you can see that just before the excution pointer is in your EXE's, it is in fact executing in ntdll which is part of Windows. By using "ret" it exits your program and returns the code pointer back to ntdll in the same way that you can exit a sub routine. As far as Windows is concerned, your program is just a sub routine in Windows.

But does using "ret" leave some things in a "not cleaned up" state, things that WOULD be cleaned up if you ran the ExitProcess function?

When I used to program under Win32, I would always use both. ExitProcess allows you to specify whether your program completed execution successfully and gives the operating system a chance to finalize any threads that have been created by your program. And the RET instruction will return you back to the operating system's code.

Also, which is the more correct way of marking the executable code section of your assembly code? Is it better to use "SEGMENT .text" or SEGMENT .code"? I've seen some examples that use the ".text" version of this line, and some that use the ".code" version of this line.

I would suggest you get away from ALINK and the old OMF objects ASAP. For most newer code you'll almost always see "SECTION .text" for your executable code section. Under the older OMF objects it was common to use names like "CODE" or "CSEG" since it was just a random symbol and didn't actually matter.

About Bryant Keller
bkeller@about.me