I am trying to build a basic win32 exe using masm. I only need the essentials (just want it to be able to compile and run). My code is below. I also get the following error when trying to compile it "ml test.am":
/z2
"test.obj"
"test.exe"
NUL
LINK : warning LNK4044: unrecognized option "z2"; ignored
test.obj : warning LNK4033: converting object format from OMF to COFF
LINK : fatal error LNK1181: cannot open input file "test.exe"
.386
.model flat
.CODE
start:
xor eax, eax
END
What am I doing wrong? Thanks
.386
.model flat, stdcall
.code
start:
xor eax,eax
end start
"end start" is required to indicate the end of the section (don't ask me why :P)
I tried to remove the calling convention "stdcall" but that caused complaints :wink
A minimal (useful?) program looks like this (in fact, this is what I usually use a starting template :bg)
.386
.model flat, stdcall
option casemap:none
include windows.inc
include kernel32.inc
includelib kernel32.lib
.code
start:
invoke ExitProcess, NULL
end start
Hi hippofear!
To successfully compile it, are needed at least 2 changes (this says Tedd too):
.386
.model flat,stdcall ;not only stdcall
.CODE
start:
xor eax, eax
end start ;not only end
Inlude are needed, if You want to use some system API's. ExitProcess is used to correctly end Your exe.
YOu need to use:
ml /c /coff test.asm
link /subsystem:windows test.obj
to compile.
You also need a ret or an invoke ExitProcess,0 after the xor eax,eax
thanks a lot guys.
AeroASM: can you tell me why i had to use the commands you posted to compile above^ instead of only "ml test.asm"?
Just ml file.asm would produce a raw object file. You need to make sure you assemble the right type of object file and then feed it to the linker to make an executable.
hipppofear,
All these answers are excellent. If I were you, I would save Tedd's template code and use it as the start of every program you make. Also, save Aero's code as a batch file called makeit.bat. As time goes on you will add more to it but it is a working beginning for you.
hipppofear is an interesting handle.
Paul
if you want the ABSOLUTE basic:
.386
.MODEL FLAT
INCLUDELIB Kernel32.lib
ExitProcess PROTO STDCALL,:DWORD
.CODE
_Start:
INVOKE ExitProcess, 0
END _Start
thanks again.
I have an off the topic questions, the instruction below gives me the following error:
Assembling: test.asm
test.asm(28) : error A2070: invalid instruction operands
cmp [esi+eax], 0
I want to compare the value located at esi+eax and 0. this worked in other compilers but im not sure why it doesnt with masm. I tried "cmp dword [esi+eax], 0" but it didnt work.
hipppofear,
MASM needs to know what size and type of memory variable to compare to zero.
cmp dword ptr [esi+eax], 0
You were close with 'dword', in MASM it has to be 'dword ptr'.
Be sure to skim over the ASMINTRO.HLP file in \masm32\help - this will answer a lot of questions. :bg
Quote from: Robert Bieber on July 27, 2005, 06:29:57 PM
Just ml file.asm would produce a raw object file. You need to make sure you assemble the right type of object file and then feed it to the linker to make an executable.
You mean ml /c file.asm
WIthout the /c it tries to link it as well.
hipppofear,
You get these odd problems because most people use the shorthand notation in MASM where you only specify the data size if ther operands do not. When you write an instruction like the following,
cmp [esi+eax], 0
You have a memory operand and an immediate value and neither tell the assembler the size required so the shorthand form does not work. You can successfully write MASM with fully specified sizes with code like,
mov DWORD PTR [eax], edi
or
cmp DWORD PTR [esi+eax], 0
and it works fine but where the asembler can work out the size from the operands, it does not have to be done.
Which means to say, if you prefer the shorthand notation method, you can do it this way:
xor ebx, ebx
cmp [eax+esi], ebx
or you can declare a variable as dword and use that:
anything DWORD 0
cmp [eax+esi], anything
Using either method, you can use any value that fits into the size of a DWORD, not just zero.
either way works but the second method is preferable as it does not tie up an extra register
Paul
You actually need an OFFSET with the .data section operand.
.data
anything DWORD 0
.code
cmp [eax+esi], OFFSET anything
Here is te disassembly of the three.
00401023 813C0618304000 cmp dword ptr [esi+eax],403018h
0040102A 33C0 xor eax,eax
0040102C 390406 cmp [esi+eax],eax
0040102F 833C0600 cmp dword ptr [esi+eax],0
Doing a direct compare to an immediate zero is the smallest because of how the opcodes work for an immediate that is within BYTE range, te XOR version is next and the compare to a value in the .DATA section is the largest.
Hutch,
I am aware of that, but this is the Campus not the Workshop. I think I have gone on record often enough about optimizations not being something that the beginner should worry about. But, you are a good coder and of course you are right.
I just wanted to show what you were alluding to but did not explain, because this is the Campus. :U
Paul