I've started to learn assembly and tried to compile the following code on visual studio 2010
DSEG SEGMENT
A DW 8
B DW 10
DSEG ENDS
SSEG SEGMENT STACK
DW 100H DUP(?)
SSEG ENDS
CSEG SEGMENT
ASSUME CS:CSEG, DS:DSEG, SS:SSEG
MAIN PROC FAR
PUSH DS
MOV AX, 0
PUSH AX
MOV AX, DSEG
MOV DS, AX
; The start of the program
MOV AX, A
MOV BX, B
ADD AX, BX
MOV A, AX
RET
MAIN ENDP
CSEG ENDS
END MAIN
I got the following errors:
1>main.asm(17): error A2004: symbol type conflict
1>main.asm(32): warning A4023: with /coff switch, leading underscore required for start address : MAIN
1>C:\Program Files\MSBuild\Microsoft.Cpp\v4.0\BuildCustomizations\masm.targets(49,5): error MSB3721: The command "ml.exe /c /nologo /Zi /Fo"Debug\main.obj" /W3 /errorReport:prompt /coff /Tamain.asm" exited with code 1.
I searched the web for a soulution and the only thing I found is that error A2004 happes because the /coff directive.
How can I remove the /coff from the argument list? (If this is what cusing This error to apeare).
Thanks,
Ido Sorozon
If you are learning the assembly language basics, you should give a try with emu8086: it is a tool dedicated to assembly learning that features a Masm compatible assembler with support for macros (it can also support fasm syntax) and a 8086 cpu simulator with DOS screen emulation to test / debug your work.
It makes it possible to produce 16 bit COM programs, old fashioned EXEs and even boot sectors.
The sample program that you show in your question assembles without problem with that tool.
Related
I am studying assembler for the x86 family of processor architectures (32-bit and 64-bit) on Windows. It is not to say that I'm quite a beginner, but I probably don't know everything, at least about the syntax of the MASM assembler, as it seems.
I use the MASM assembler (for 64-bit programs) located in folders belonging to Visual Studio:
"..\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30133\bin\Hostx64\x64\ml64.exe"
Visual Studio 2019 is installed, and I use the MASM assembler from its folder. I have Windows 7 myself.
I made my program for a 32-bit system, and it was normally assembled by MASM for 32-bit programs and worked. Then I translated its code for a 64-bit architecture (and there are a few changes needed in the code there). But, when assembling it with MASM for 64-bit programs, MASM gave an error message that there was allegedly some unresolved "StartOfProgram" symbol. Here's what's in the console:
C:\Assembler>cd "C:\Assembler"
C:\Assembler>"C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30133\bin\Hostx64\x64\ml64.exe" "C:\Assembler\Main.asm" /link /subsystem:windows /entry:StartOfProgram
Microsoft (R) Macro Assembler (x64) Version 14.29.30138.0
Copyright (C) Microsoft Corporation. All rights reserved.
Assembling: C:\Assembler\Main.asm
Microsoft (R) Incremental Linker Version 14.29.30138.0
Copyright (C) Microsoft Corporation. All rights reserved.
/OUT:Main.exe
Main.obj
/subsystem:windows
/entry:StartOfProgram
LINK : error LNK2001: unresolved external symbol StartOfProgram.
Main.exe : fatal error LNK1120: unresolved external symbols: 1
I spent about two weeks or month searching for solution to this error, but I didn't find it.
In general, it used to give an error message that allegedly there is some unresolved symbol "WinMainCRTStartup", but recently I kind of realized that it made such an entry point, because I did not explicitly specify entry point in the console (via the command "/entry:", which is in the console from above), but the problem about "unresolved external symbol" remained, even though I set the entry point where I needed it (that is, on "StartOfProgram").
Here is the code of my 64-bit version of the program that just has to output "Hello world" in a pop-up window:
option casemap:none ; As far as i understand, functions from Windows API without case sensitivity not works
; **** Importing what needs ****
includelib "C:\Program Files (x86)\Windows Kits\10\Lib\10.0.19041.0\um\x64\kernel32.lib" ; Downloading main static library to use main functions of Windows API
extern LoadLibraryA:near ; I load from static libraries functions used in this program
extern GetProcAddress:near
extern FreeLibrary:near
extern ExitProcess:near
; **** Declaring memory segment ****
.data
text db 'Hello world', 0 ; Text in "Text Box"'s window
header db 'Title of hello world', 0 ; Header of "Text Box"'s window
nameOfDLL db 'user32.dll', 0
nameOfProcedureOfDLL db 'MessageBoxA', 0
handlerToModule dd 0
addressOfProcedureOfDLL dq 0 ; In 64-bit operating system, addresses are 64-bit, so size of memory area that this label points to - is quad word (dq) (that is 64 bits)
.code
; **** Entry point to program ****
StartOfProgram: ; For some reason, MASM assembler recommends putting "_" sign before label of entry point to program, if it is 32-bit. Therefore in 64-bit I don't.
mov rcx, offset nameOfDLL
sub rsp, 40 ; Pointer shifting for alignment of stack and plus "shadow space" in stack. It needed by x64 calling convention
call LoadLibraryA ; I dynamically connect DLL so that i can then take function from it
add rsp, 40
mov qword ptr handlerToModule, rax
mov rcx, rax ; Functions from Windows API use stdcall convention. stdcall is agreement to pass function parameters to stack backwards, so rax is last. Rax still contains Windows' DLL address (Microsoft call it "handler") (after recent call to Loadlibrary function), so it's better to use register, processor works faster with registers
mov rdx, offset nameOfProcedureOfDLL
sub rsp, 40
call GetProcAddress
add rsp, 40
mov addressOfProcedureOfDLL, rax ; I save address of procedure that i took from GetProcAddress. In 64-bit operating system, addresses are 64-bit, so needs to transfer rax register and not eax
mov rcx, 0
mov rdx, offset text
mov r8, offset header
mov r9, 0
sub rsp, 40
call addressOfProcedureOfDLL ; It is better to immediately pass address of function through memory address label and not through register containing this address, because computer will still have to go to this address later and there is no point in wasting time reading from register of same address
add rsp, 40
mov rcx, offset handlerToModule
sub rsp, 40
call FreeLibrary
add rsp, 40
mov rcx, 0
sub rsp, 40
call ExitProcess
add rsp, 40
end
Here is the code of my 32-bit version of this program (which was normally assembled and worked):
.386 ; There indicates processor with minimal set of functions (since new Intel processors (in "x86" family of architectures) are compatible (so far) with instructions of old Intel processors of same family of architectures)
option casemap:none ; As far as i understand, functions from Windows API without case sensitivity not works
; **** Importing what needs ****
includelib "C:\Program Files (x86)\Windows Kits\10\Lib\10.0.19041.0\um\x86\kernel32.lib" ; Downloading main static library to use main functions of Windows API
;includelib "C:\Program Files (x86)\Windows Kits\10\Lib\10.0.19041.0\um\x86\User32.lib"
extern _LoadLibraryA#4:near ; I load from static libraries a functions used in this program
extern _GetProcAddress#8:near
extern _FreeLibrary#4:near
extern _ExitProcess#4:near
.model flat
; **** Declaring a memory segment ****
.data
text db 'Hello world', 0 ; Text in "Text Box"'s window
header db 'Title of hello world', 0 ; Header of "Text Box"'s windowокна
nameOfDLL db 'user32.dll', 0
nameOfProcedureOfDLL db 'MessageBoxA', 0
handlerToModule dd 0
addressOfProcedureOfDLL dd 0
.code
; **** Entry point to program ****
_StartOfProgram: ; For some reason, MASM assembler recommends putting "_" sign before label of entry point to program, if it is 32-bit
push offset nameOfDLL
call _LoadLibraryA#4 ; I dynamically connect DLL so that i can then take function from it
mov handlerToModule, eax
push offset nameOfProcedureOfDLL
push eax ; Functions from Windows API use stdcall convention. stdcall is agreement to pass function parameters to stack backwards, so eax is last. Eax still contains Windows' DLL address (Microsoft call it "handler") (after recent call to Loadlibrary function), so it's better to use register, processor works faster with registers
call _GetProcAddress#8
mov addressOfProcedureOfDLL, eax ; I save address of procedure that i took from GetProcAddress
push 0
push offset header
push offset text
push 0
call addressOfProcedureOfDLL
push handlerToModule
call _FreeLibrary#4
push 0
call _ExitProcess#4
end _StartOfProgram
And here is result of 32-bit version of program:
Result of 32-bit version of program
The problem was been solved in comments. As said by #Peter Cordes and #David Wohlferd, I needed to publish my label in my program by directive "public" and then writing the name of the label, or rewrite my entry-point-label with using directive "proc" and "endp" with name of label at beginning of this directives.
I prefer a solution through the "public" directive, because I think it is closer to low-level programming. In this case, I had to make my label public in my program using the "public" directive, and then write the name of the label at the end of it, to become available to external programs. The MASM assembler, apparently, gave an error due to fact that it did not see it accessible from the outside and therefore did not consider it correct to assign it as the entry point, although it could guess that if I specify it as entry point, then it is available for switching to it from the outside. Apparently, the developers of MASM didn't do this.
Here is an example of using directive "public" in my program (I used directive "public"):
public StartOfProgram
And I noticed that I can put it anywhere in my code.
Here is an example of using directive "proc" and "endp" in my program:
StartOfProgram proc ; - Beginning of this directivical procedure
; ... there may be the code itself inside this directivical procedure
StartOfProgram endp ; - End of this directivical procedure
My code in the question had other errors, separate from the theme of this question; I've corrected it there.
I have a problem with the MASM32 assembler
The following code is a Hello World example that I copied from the MASM32 tutorial:
.model small
.stack
.data
message db "Hello world!", "$"
.code
_main proc
mov ax,seg message
mov ds,ax
mov ah,09
lea dx,message
int 21h
mov ax,4c00h
int 21h
_main endp
end _main
On attempt to assemble, MASM32 throws A2004 error with the following comment:
C:\masm32\console.asm(11) : error A2004: symbol type conflict
Can anyone help me with that?
This code worked perfectly fine with the TASM assembler, but now I have to use MASM32 and I am having this A2004 error for any assembly code that I've earlier proven to work with TASM.
In case this is relevant, I am have a 32bit CPU running Win7 OS.
Thanks.
I'm pretty certain that .model small and seg are artefacts of an earlier age when the x86 architecture was truly segmented (into 64K chunks).
The masm32 IDE doesn't like them very much at all (not unexpected since it's far more common nowadays to be doing 32-bit flat model code).
The problem lies in the fact that the bin\assmbl.bat file is being used by the editor to assemble the file and it contains the line:
\masm32\bin\ml /c /coff %1.asm > \masm32\bin\asmbl.txt
(with the /coff option). This is what's making the assembler complain.
You can get it to work by reverting to the command line. Assuming your file is tst.asm, use the following commands:
c:\masm32\bin\ml.exe /c tst.asm
c:\masm32\bin\link16 tst.obj.tst.exe,,,,
and you'll have a tst.exe that works fine.
The following transcript shows that this works:
C:\masm32> type tst.asm
.model small
.stack
.data
message db "Hello world!", "$"
.code
_main proc
mov ax,seg message
mov ds,ax
mov ah,09
lea dx,message
int 21h
mov ax,4c00h
int 21h
_main endp
end _main
C:\masm32> bin\ml.exe /c tst.asm
Microsoft (R) Macro Assembler Version 6.14.8444
Copyright (C) Microsoft Corp 1981-1997. All rights reserved.
Assembling: tst.asm
C:\masm32> bin\link16 tst.obj,tst.exe,,,,
Microsoft (R) Segmented Executable Linker Version 5.60.339 Dec 5 1994
Copyright (C) Microsoft Corp 1984-1993. All rights reserved.
C:\masm32> tst.exe
Hello world!
Alternatively, the editor is very configurable. If you open up the menus.ini file for editing (back it up first, I shouldn't need to tell you that) and change:
&Assemble ASM file,\MASM32\BIN\Assmbl.bat "{b}"
to:
&Assemble ASM file,\MASM32\BIN\Assmbl.bat "{b}"
Assemble ASM file (no COFF),\MASM32\BIN\Assmbl2.bat "{b}"
you can get your new menu item added on IDE restart.
You also need to copy bin\assmbl.bat to bin\assmbl2.bat and remove the /coff from the latter.
Then you can compile fine from within the IDE with the new menu option.
Of course, you'll have to do the same thing for the link and assemble/link menu items as well. But, now that you know how it's done, that shouldn't present a problem.
It's been a while since I used MASM - but isn't 'message' a reserved word? try '_message'.
I am trying to run the following code in Visual Studio 2015 that has MASM built in to it. I am trying to link the Irvine library files to the program. However, I get like 49 of the following errors.
A2C \Irvine\SmallWin.inc(11)or specified size
A2C \Irvine\SmallWin.inc(12)or specified size
A2C \Irvine\SmallWin.inc(299)for specified size
Here is my code
ExitProcess PROTO
includelib C:\Irvine\Kernel32.Lib
includelib C:\Irvine\User32.Lib
includelib C:\Irvine\Irvine32.lib
include Irvine32.inc
.data
str1 BYTE "This line is displayed in color",0
.code
main PROC
mov eax, black + (white * 16) ; black on white backgrouund
mov ecx,4 ; loop counter
L1: call SetTextColor
mov edx,OFFSET str1
call WriteString
call Crlf
add eax,2 ; add 2 to foreground color
loop L1
call ExitProcess
main ENDP
END
Why are the Irvine libraries not linking?
Trying to compile a 32-bit program in a 64-bit MASM program application. Need to setup Visual Studios for 32-bit assembly language project.
I want to write 16 bit 8086 assembly code in visual studio 2010
but gives me error:
code:
.MODEL small
.STACK 100h
.data
message BYTE "Hello, world!","$"
.code
_start:
mov ah,9
lea dx,message ; addr of buffer
int 21h
END _start
output gives me this error:
Link:
Microsoft (R) Segmented Executable Linker Version 5.60.339 Dec 5 1994
Copyright (C) Microsoft Corp 1984-1993. All rights reserved.
warning L4017: /ERRORREPORT : unrecognized option name; option ignored
LINK : fatal error L1093: Files\Microsoft Visual Studio 10.0\VC\bin\link.exe :
object file not found
Build FAILED.
what should I to do?
Really not sure what the problem is. I have never uses VS for Assembly. There are great Assembly IDEs out there that are better than VS IMHO - RadASM, WinASM.
This code:
.MODEL small
.STACK 100h
.data
message BYTE "Hello, world!","$"
.code
_start:
mov ah,9
lea dx,message ; addr of buffer
int 21h
END _start
Assembles and links fine with this batch file:
#ECHO ON
del dosdisplay.exe
ML.EXE /DMASM /DDOS /Zm /c /nologo /I"d:\masm32\Include" "dosdisplay.asm"
link16.exe /NOLOGO "dosdisplay.obj" "",,,,,""
Assembler and Linker versions that I use:
Microsoft (R) Macro Assembler Version 6.15.8803
Microsoft (R) Segmented Executable Linker Version 5.60.339 Dec 5 1994
What is link? Isn't that the 32bit version? or is the 16bit name the same? Not sure, been using these 2 files/versions for many, many years for DOS apps.
This problem is arise:
1.due to the long name of .asm file. Shorten your file name and get your desired results.
2.due to wrong path when linking your file.
I want to write 16 bit 8086 assembly code in visual studio 2010
but gives me error:
code:
.MODEL small
.STACK 100h
.data
message BYTE "Hello, world!","$"
.code
mov ah,9
mov dx,OFFSET message ; addr of buffer
int 21h
END
output gives me this error:
fm.obj : fatal error LNK1190: invalid fixup found, type 0x0001
I using masm32v11. What should I do?
Where does the Assembler know where the starting address is?
Using Microsoft (R) Segmented Executable Linker Version 5.60.339 Dec 5 1994 (16bit linker)
and added start and end start the code Assembles and links just fine. MASM32 includes a 16bit linker in the bin directory. You must pass different command line parameters to ML to Assemble 16bit code correctly though.
.MODEL small
.STACK 100h
.data
message BYTE "Hello, world!","$"
.code
start:
mov ah,9
mov dx,OFFSET message ; addr of buffer
int 21h
END start
So to recap - your code needs a starting address and an end,
You can use the current ML that comes with MASM32 to Assemble 16 bit and 32 bit code. To link 16 bit code you must use a 16 bit linker, to link 32 bit code, you must use a 32 bit linker.
From one of my 16 bit DOS apps:
ML.EXE /DMASM /DDOS /Zm /c /nologo /I"f:\masm32\Include" "dosdisplay.asm"
link16.exe /NOLOGO "dosdisplay.obj"
Assemble and link with these commands:
ml.exe /omf filename.asm
link16.exe filename.obj
Info:
When you invoke ml.exe without any specific parameters the type of object file that it generates will be in COFF format. COFF format name mangling requires that your code should have a _start and end _start. what you have written will work for Intel's OMF object files.