i've got this code to just print out whatever is in the register ax currently:
.686p
.xmm
.model flat,c
.stack 4096
; include C libraries
includelib msvcrtd
includelib oldnames
includelib legacy_stdio_definitions.lib
; imported functions
extrn printf:near
.data ; initialized global vars
IntegerFormat db "The result is: %d",0dh,0ah,0
.code
public main
main proc
; your logic goes here.
mov ax, 3
movsx eax, ax
push eax
push offset IntegerFormat
call printf ; call printf(IntegerFormat, 3)
add esp, 8
xor eax,eax
ret
main endp
end
i've created a C++ empty project and added this .asm file.
It didn't run, so I did what's written here:
Compiling assembly in Visual Studio
And it worked.
But now, whenever I update the code and build, for example i changed mov ax, 3 to mov ax, 4
It still prints out 3.
The only way that seems to solve it is setting the item type (in the properites of the .asm file) to does not participate in build, and then do what written in the link I provided again.
Is there any way to change it so it compiles the new code version every time without having to do the process I described above every time?
Thanks in advance!
Related
Pretty new to assembly, having fun poking at it. I am wanting to split the functionality of my program across multiple files, specifically by grouping similar functions together for organization. These other files would be called by the main file (and hopefully even other non-main files). I haven't yet managed to do so, and would like help.
I am not using an IDE, preferring to use notepad++, ml.exe, and link.exe (from MASM folder) to write, assemble, and link the program myself. Most online resources I have looked at assume Visual Studio, and give code that doesn't work for me, or maybe is incomplete b/c the IDE does something else. I do not intend to start using an IDE.
I would like to learn the "best" way, meaning, the way that is most useful for future projects. Can I set it up in such a way that I can just copy the file and write a couple lines of code to use it in a different project in the future? Or maybe that's bad practice and I should learn a more standard method instead? I understand this platform is not for opinionated questions, and I'm hoping this question is more factually based than opinion.
All useful info I can think of:
Language: Masm assembly x86
Computer: 64 bit Windows
Code:
RUN.bat
#echo off
ml /c /coff /Zi /Fl Driver.asm
ml /c /coff /Zi /Fl Utils.asm
link /debug /subsystem:console /entry:start /out:Driver.exe Utils.obj Driver.obj \masm32\lib\kernel32.lib
Driver.exe
pause
Driver.asm
.386
.model flat
.stack 100h
ExitProcess PROTO Near32 STDCALL, dwExitCode:DWORD
ClearRegs PROTO
.DATA
.CODE
PUBLIC _start
_start:
Main PROC
MOV EAX, 0
INVOKE ClearRegs
INVOKE ExitProcess, 0
Main ENDP
END
Utils.asm
.386
.model flat
.stack 100h
OPTION PROC:PRIVATE ; Set procedures to private by default
PUBLIC ClearRegs
.DATA
.CODE
ClearRegs PROC C
XOR EAX, EAX
XOR EBX, EBX
XOR ECX, ECX
XOR EDX, EDX
XOR ESI, ESI
XOR EDI, EDI
RET
ClearRegs ENDP
END
Terminal output
Microsoft (R) Macro Assembler Version 6.14.8444
Copyright (C) Microsoft Corp 1981-1997. All rights reserved.
Assembling: Driver.asm
Microsoft (R) Macro Assembler Version 6.14.8444
Copyright (C) Microsoft Corp 1981-1997. All rights reserved.
Assembling: Utils.asm
Microsoft (R) Incremental Linker Version 5.12.8078
Copyright (C) Microsoft Corp 1992-1998. All rights reserved.
Driver.obj : error LNK2001: unresolved external symbol ClearRegs
Driver.exe : fatal error LNK1120: 1 unresolved externals
'Driver.exe' is not recognized as an internal or external command,
operable program or batch file.
Press any key to continue . . .
Now that your question has been updated with a minimal, complete, verifiable example some specific problems can be identified. When you declare a function with PROC there is a language naming and calling convention applied to each function. Not specifying one associates no special processing.
You can specify a default language with the model directive as a second parameter. In both your files you have used:
.model flat
So you haven't associated a default language. You have defined ClearRegs as:
ClearRegs PROC C
[snip]
ClearRegs ENDP
The problem here is that PROC C specifies the C language calling convention and naming convention. With COFF format (32-bit) the C naming convention requires an underscore (_) to be prepended to the beginning of the function name. If you were to generate a MAP file you'd discover that the Function name exported from utils.asm is actually _ClearRegs and not ClearRegs.
There are a number of ways to fix this. You can choose not to add a default language to the .model directive and tell Driver.asm that ClearRegs is defined as a C PROTOtype by changing:
ClearRegs PROTO
to
ClearRegs PROTO C
So now utils.asm is exporting _ClearRegs and Driver.asm is importing _ClearRegs as both sides match and MASM will handle adding the extra underscore. INVOKE ClearRegs will use the naming convention associated with the PROTO statement which says the language is C so it will add the extra _ for you.
This brings up an additional change you can make. An END directive can be used to specify the entry point to your program rather than using /entry:<name> on the linker command line. The entry point has to have a name that starts with an _ to satisfy the linker.
You currently use this in Driver.asm:
PUBLIC _start
_start:
Main PROC
[snip]
Main ENDP
END
And you use /entry:start when linking. You could change this to be:
_Main PROC
[snip]
_Main ENDP
END _Main ; END with a function name tells linker to use _Main as program entry point
When linking you can now remove the /entry option altogether and you don't need the _start label anymore. We can do better though. The entry point called by the MS C Runtime startup assumes the function is following the C language naming and calling convention. What is preferable is to do this:
Main PROC C
[snip]
Main ENDP
END Main ; END with a function name tells linker to use _Main as program entry point
If you intend to make all your functions PROC C then you can avoid specifying C in most places by changing the default language in both Utils.asm and Driver.asm by changing:
.model flat
to:
.model flat, C
This will change the default for PROTO statements, PUBLIC statements specifying a function defined with PROC and PROC statements themselves. Your code in Driver.asm could look like:
.386
.model flat, C
.stack 100h
ExitProcess PROTO Near32 STDCALL, dwExitCode:DWORD
ClearRegs PROTO
.DATA
.CODE
Main PROC
MOV EAX, 0
INVOKE ClearRegs
INVOKE ExitProcess, 0
Main ENDP
END Main
Utils.asm could look like:
.386
.model flat, C
.stack 100h
OPTION PROC:PRIVATE ; Set procedures to private by default
PUBLIC ClearRegs
.DATA
.CODE
ClearRegs PROC
XOR EAX, EAX
XOR EBX, EBX
XOR ECX, ECX
XOR EDX, EDX
XOR ESI, ESI
XOR EDI, EDI
RET
ClearRegs ENDP
END
And you'd link with:
link /debug /subsystem:console /out:Driver.exe Utils.obj Driver.obj \masm32\lib\kernel32.lib
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.
Visual Studio 2015
I compile simple code, but the compilation result (Release) has 4Kb size. Why does it happen? This is complete code source of my project:
ExitProcess PROTO
.data
qword1 qword 12345678ffeeddcch
.code
main proc
mov rax, 2c5h
mov rbx, qword1
mov rcx, 0
call ExitProcess
main endp
end
When an executable file is compiled, it includes a lot of information it uses for its execution; only a small section of the data in the executable is the actual code. A good example of this is when an assembly program uses C functions via extern. Here's an article on the subject if you'd like to read more about it: More info on PE Format
Hello Stack Overflowers!
I have wrote a asm code file that i'm trying to build using ml64 (v14.00.23506.0)
but the assembler gives me weird output.. like there something wrong in line 1..
i'm sure there is nothing wrong with the code because it worked well on other ml64 version. it worked well with the ml64 from VS Community 2015, the current ml64 from VC++ BuildTools Tech-Preview gives me the error in the screenshot.
i tried ml64 from VS Express 2015 and VC BuildTools 2015 TP, both give same error.
ps. im building with a batch script that i wrote and coding in VIM.
can anyone guide me on how to overcome this issue?
-- UPDATED --
that's the cmd build error after i fixed the previous batch errors.
still weird error, can anyone understand?
(thats a test code)
includelib kernel32.lib
includelib user32.lib
EXTERN GetModuleHandleExW:PROC
EXTERN MessageBoxW:PROC
EXTERN ExitProcess:PROC
.DATA
ALIGN 4
pwszMessage WORD "H","e","l","l","o",","," ","W","o","r","l","d","!"
WORD 0
pwszCaption WORD "M","e","s","s","a","g","e","B","o","x"
WORD 0
hInstance QWORD 0
.CODE
entry PROC
sub rsp, 28h
xor rcx, rcx
mov rdx, rcx
lea r8, [hInstance]
call GetModuleHandleExW
lea rdx, [pwszMessage]
lea r8, [pwszCaption]
mov r9d, 40h
call MessageBoxW
call ExitProcess ; rcx suppose to hold 0 already
add rsp, 28h
ret
entry ENDP
END
A while ago I posted this question regarding strange behavior I was experiencing in trying to step through a MASM program.
Essentially, given the following code:
; Tell MASM to use the Intel 80386 instruction set.
.386
; Flat memory model, and Win 32 calling convention
.MODEL FLAT, STDCALL
; Treat labels as case-sensitive (required for windows.inc)
OPTION CaseMap:None
include windows.inc
include masm32.inc
include user32.inc
include kernel32.inc
include macros.asm
includelib masm32.lib
includelib user32.lib
includelib kernel32.lib
.DATA
BadText db "Error...", 0
GoodText db "Excellent!", 0
.CODE
main PROC
int 3
mov eax, 6
xor eax, eax
_label: add eax, ecx
dec ecx
jnz _label
cmp eax, 21
jz _good
_bad: invoke StdOut, addr BadText
jmp _quit
_good: invoke StdOut, addr GoodText
_quit: invoke ExitProcess, 0
main ENDP
END main
I could not get the int 3 instruction to trigger. It was clear why it didn't, examining the disassembly:
00400FFD add byte ptr [eax],al
00400FFF add ah,cl
--- [User path]\main.asm
mov eax, 6
00401001 mov eax,6
xor eax, eax
00401006 xor eax,eax
_label: add eax, ecx
The int 3 instruction had been replaced with add al,cl, but I had no idea why. I managed to track the problem to whether or not Incremental Linking was enabled. The above disassembly was generated with Incremental Linking disabled (/INCREMENTAL:NO option on the command line). Re-enabling it would result in something like the following:
.CODE
main PROC
int 3
00401010 int 3
mov eax, 6
00401011 mov eax,6
xor eax, eax
00401016 xor eax,eax
I should note that the interleaving lines are references back to the original code (I guess a feature of Visual Studio's disassembly window). With Incremental Linking enabled, the disassembly corresponds exactly to what I had written in the program, which is how I expected it to behave all along.
So, why would disabling Incremental Linking cause the disassembly of my program to be altered? What could be happening behind the scenes that would actually alter how the program executes?
The "add" instruction is a two byte instruction, the second of which is the 1-byte opcode of your int3. The first byte of the two byte add instruction is probably some garbage just before the entrypoint. The address of the add instruction is probably 1 byte before where the int3 instruction would be.
I quickly assembled and then disassembled those two instructions with GNU as en objdump, and the result is:
8: 00 cc add %cl,%ah
a: cc int3
Here you can clearly see that the the add instruction contains the second byte 0xcc, while int3 is 0xcc
IOW make sure that you start disassembling on the entry point to avoid this problem.