I've been using Visual Studio to assemble and link cpp programs that include masm (.asm) files. I want to be able to do this myself, on the command line. I used the ml.exe that Visual Studio provides to assemble my masm code (at Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30133\bin\Hostx86\x86\ml.exe).
However, when I try to compile my project with gcc main.cpp fib.obj -o main, I get an error saying that the .obj architecture does not match the target architecture (i386 architecture of input file 'fib.obj' is incompatible with i386:x86-64 output).
So my question is, simply, how do I compile this project?
What I've Tried
The two things that I've done to get different errors (which I think are more promising) are (1) to utilize the ml64 executable from ...\Hostx86\x64\ml64.exe or ...\Hostx64\x64\ml64.exe, and (2) to use the -m32 option for gcc.
ml64
Using ml64 I have been unable to assemble my masm code. with the following source file, ml64 spits out this response:
; int fib(int);
.386
.model flat, c
.code
fib proc uses ebx ecx, i:dword
mov eax, 0 ; current fib number
mov ebx, 1 ; next fib number
while_1:
cmp i, 0
jle while_1_end
; add eax -> ebx and mov previous ebx into eax
mov ecx, ebx ; store new current fib number
add ebx, eax ; sum previous fib numbers
mov eax, ecx ; set eax to current fib value
dec i
jmp while_1
while_1_end:
; the ith fib number is in eax
ret
fib endp
end
...\fib> ml64 fib.asm
Microsoft (R) Macro Assembler (x64) Version 14.29.30136.0
Copyright (C) Microsoft Corporation. All rights reserved.
Assembling: fib.asm
fib.asm(2) : error A2008:syntax error : .
fib.asm(3) : error A2008:syntax error : .
fib.asm(6) : error A2008:syntax error : ebx
fib.asm(24) : fatal error A1010:unmatched block nesting : fib
I presume that .386 isn't right for a x64 target, but removing it changes the error very little (it only removes the syntax error line 2).
I don't really want to use x64 assembly if it isn't the same as x32, but I'll use this solution if it works. I think my second option is more promising.
gcc -m32
I don't believe I can tell gcc to build to a 32-bit target because I don't have 32-bit versions of the libraries. When running gcc -m32 main.cpp fib.obj I get cannot find -lmingw32, cannot find -lgcc, cannot find -lgcc_ex, etc. Should I get these libraries, and if so, where do I find them? It seems a bit awful to download 32-bit libraries on my x64 computer just to assemble masm, and I don't think I should have to, seeing as Visual Studio is able to compile my project simply by setting the target to Win32.
Is there a different way of telling gcc to target 32-bit architecture, or are the libraries perhaps hidden in the Visual Studio files, or something else? I'm pretty sure that if I could get gcc to target x32, it would solve my problem, because Visual Studio targets x32, and when I change the target to x64 I get the same error I have been getting (module machine type 'x86' conflicts with target machine type 'x64').
Related
I'm frankly not even sure if this is a thing GDB can do, but no amount of searching I've done so far has given me a 'yes' or 'no'.
When I attempt to debug an application using a GDB installation built for Linux and opened in WSL, it is unable to insert a breakpoint anywhere in the program, claiming it can not access the memory at that address. If I do this from Windows with a GDB built for Windows, this error does not happen (and before you ask why I don't just use the Windows build, it's because I'm having other miscellaneous issues with that one. I may open a question for that as well)
I've got an internal error from GDB as well, but unfortunately, I can't seem to recreate it right now.
I've tried rebuilding GDB, as well as switching to another version of GDB (the same as my Windows build)
I'm using a WSL installation of Ubuntu 20.04 and GDB 10.2, configured as follows:
(gdb) show configuration
This GDB was configured as follows:
configure --host=x86_64-pc-linux-gnu --target=x86_64-pc-linux-gnu
--with-auto-load-dir=$debugdir:$datadir/auto-load
--with-auto-load-safe-path=$debugdir:$datadir/auto-load
--without-expat
--with-gdb-datadir=/usr/local/share/gdb (relocatable)
--with-jit-reader-dir=/usr/local/lib/gdb (relocatable)
--without-libunwind-ia64
--without-lzma
--without-babeltrace
--without-intel-pt
--without-mpfr
--without-xxhash
--without-python
--without-python-libdir
--without-debuginfod
--without-guile
--disable-source-highlight
--with-separate-debug-dir=/usr/local/lib/debug (relocatable)
To see if this was an issue with the particular program I was debugging, I made a very minimal program in NASM (my original project was also in NASM) and compiled it as follows:
nasm -f win32 -gcv8 Test.asm
gcc -m32 -g Test.obj -o Test.exe
The source assembly is very simple. It just calls printf with a string and integer.
; Test.asm
global _main
extern _printf
section .data
fmt: db "%s, %d", 0x0
string: db "Testing...", 0x0
section .bss
num: resd 1
section .text
_main:
mov dword [num], 28
push dword [num]
push string
push fmt
call _printf
add esp, 12
ret
When attempting to debug this with GDB in WSL, this is the output I get:
(gdb) file Test.exe
Reading symbols from Test.exe...
(gdb) set architecture i386:x86-64
The target architecture is set to "i386:x86-64".
(gdb) start
Temporary breakpoint 1 at 0x401520
Starting program: /mnt/c/NASM/Test.exe
Warning:
Cannot insert breakpoint 1.
Cannot access memory at address 0x401520
EDIT: After poking at it some more, I discovered something that seems important. GDB is only unable to access the memory and place breakpoints when the program is running. Before I've started the program, I can place breakpoints and disassemble freely.
(gdb) disas main
Dump of assembler code for function main:
0x00401520 <+0>: mov DWORD PTR ds:0x405028,0x1c
0x0040152a <+10>: push DWORD PTR ds:0x405028
0x00401530 <+16>: push 0x40300b
0x00401535 <+21>: push 0x403004
0x0040153a <+26>: call 0x40249c <printf>
0x0040153f <+31>: add esp,0xc
0x00401542 <+34>: ret
0x00401543 <+35>: xchg ax,ax
0x00401545 <+37>: xchg ax,ax
0x00401547 <+39>: xchg ax,ax
0x00401549 <+41>: xchg ax,ax
0x0040154b <+43>: xchg ax,ax
0x0040154d <+45>: xchg ax,ax
0x0040154f <+47>: nop
End of assembler dump.
(gdb) b *main+26
Breakpoint 1 at 0x40153a
(gdb) run
Starting program: /mnt/c/NASM/Test.exe
Warning:
Cannot insert breakpoint 1.
Cannot access memory at address 0x40153a
(gdb) disas main
Dump of assembler code for function main:
0x00401520 <+0>: Cannot access memory at address 0
EDIT 2:
I don't know how useful this information might be, but I did find a method that consistently causes an internal error for GDB. Starting execution of the program, then setting the architecture to auto causes an internal error every time I've tried it.
(gdb) file Test.exe
Reading symbols from Test.exe...
(gdb) start
Temporary breakpoint 1 at 0x401520
Starting program: /mnt/c/NASM/Test.exe
warning: Selected architecture i386 is not compatible with reported target architecture i386:x86-64
warning: Architecture rejected target-supplied description
Warning:
Cannot insert breakpoint 1.
Cannot access memory at address 0x401520
(gdb) set architecture auto
warning: Selected architecture i386 is not compatible with reported target architecture i386:x86-64
/mnt/c/Users/Joshua/gdb-10.2/gdb/arch-utils.c:503: internal-error: could not select an architecture automatically
A problem internal to GDB has been detected,
further debugging may prove unreliable.
If the answer to this really is as simple as "GDB built for Linux can't debug applications built for Windows"... I'll be very sad, and also quite annoyed that I was unable to find that info anywhere.
I was trying to build an exe from asm file. The asm file looks like this:
global main
extern puts
section .data
msg:
db "Hello, world!",10,0
section .text
main:
sub rsp, 28h
mov rcx, msg
call puts
add rsp, 28h
ret
Then I assembled it using NASM and tried to link it using GCC. But it is showing this error.
> nasm -fwin64 asmtest.asm
> gcc asmtest.obj
asmtest.obj: file not recognized: File format not recognized
collect2.exe: error: ld returned 1 exit status
I am unable to figure out what is going on. My NASM version 2.14.02 and GCC version 8.1.0. I have followed this tutorial (at the bottom). I am doing this on my Windows 10 64-bit machine.
I have also seen this question, but it didn't help me.
You have installed mingw for 32 bit binaries. You need to install a version of mingw configured to make 64 bit binaries to compile and/or link 64 bit binaries.
I'm trying to use MinGW-w64 to compile assembly code on Windows. The test code I am trying to compile is (I'm sure this code extremely bad, but the problem lies in the linker, not the actual code):
.intel_syntax noprefix
.text
.globl _start
_start:
push rbp
mov rbp, rsp
and rsp, -64
sub rsp, 64
mov rax, 0
leave
push 0
call _ExitProcess#4
And the command for I used for compiling is this:
gcc -nostdlib simpletest.s -o out.exe
It doesn't matter to the outcome if I add -kernel32 at the end of the command or not.
No matter what I try I keep getting the following error:
Undefined reference to '_ExitProcess#4'
I should add that the same gcc is perfectly capable of compiling C code to assembly, and then compile that assembly code to an exe.
I wrote a simple program in assembly language which will simply display a message box in windows 7 32 bit
.386
.model flat, stdcall
option casemap :none
extrn MessageBoxA#16 : PROC
extrn ExitProcess#4 : PROC
.data
HelloWorld db "Welcome to SecurityTube.net!", 0
MsgTitle db "First MessageBox", 0
.code
start:
mov eax, 0
push eax
lea ebx, MsgTitle
push ebx
lea ebx, HelloWorld
push ebx
push eax
call MessageBoxA#16
push eax
call ExitProcess#4
end start
I use following command for assembling and linking
ml /c /coff helloworld.asm
link /subsystem:windows /defaultlib:kernel32.lib /defaultlib:user32.lib helloworld.obj
Program assembled perfectly. However, while linking, i got this error:
Microsoft (R) Incremental Linker Version 5.12.8078
Copyright (C) Microsoft Corp 1992-1998. All rights reserved.
LINK : fatal error LNK1104: cannot open file "kernel32.lib"
Why i am getting this error and how to mitigate it?
The command you're looking for is:
ml.exe helloworld.asm
/coff
/link
/subsystem:windows
/defaultlib:kernel32.lib
/defaultlib:user32.lib
/libpath:C:\...somewhere...
helloworld.obj
Note that instead of running ml first with the /c switch (which assembles only without linking), and then running link, I've just combined it all into a single command line. This will run MASM to assemble the code, and then immediately link it.
The magic sauce is the /link switch, which passes every argument that comes after it to the linker.
Notice the other new switch that you did not have: /libpath. This is the one that tells the linker where the LIB files can be found. They are part of the Windows SDK, so you'll need to locate that directory on your hard disk and substitute that path for C:\...somewhere.... The exact location differs depending on which version of the SDK you have installed and how you installed it (separately, or as part of Visual Studio). If you don't have the SDK, download it here for Windows 10, or for earlier versions. (Note that the latest version is sufficient; you do not need to download every version. It supports multi-targeting.)
The documentation for MASM is all available online, including a comprehensive listing of command line options. Same thing for the linker; its options are here.
An even easier solution would be to open the Visual Studio Command Prompt and do all of your assembling and linking from there. This actually runs a batch file that sets up the environment for you so that you don't have to worry about specifying the path to all of the required SDK files (headers, libraries, etc.). You'll find this in your Start menu, or manually run:
C:\Program Files (x86)\Microsoft Visual Studio x.x\VC\bin\vcvars32.bat
to set up a 32-bit build environment.
Did you check Visual Studio's directory structure and look for $(WindowsSdkDir)\lib to see if they exist?
If not install http://msdn.microsoft.com/en-us/windows/desktop/bg162891.aspx
I want to create a valid Win32 executable, that can be run as standalone application.
For example, this simple program:
bits 32
mov eax,1
ret
I compiled it using NASM with
nasm test.asm -o test.exe
Then I ran that program.
It started NTVDM and it told me "The NTVDM CPU encountered illegal instruction" and some technical details, probably dump, and registers.
So, I want to create a standalone Win32 application in assembly language. I don't want to create COM file, like in DOS.
[section] .text
global _start
_start:
mov eax, 1
ret
can be assembled like this:
nasm -fwin32 file.asm (this should give you file.obj)
and
link /subsystem:windows /entry:start file.obj
(or)
ld -e _start file.obj
whatever linker you choose should give you your .exe
At least Windows XP refuses to load an application that does not use any DLL files. I didn't test with Windows 7 up to now!
The reason is that there are no official interfaces but the DLLs that come with Windows and that a program that has neither inputs nor outputs makes no sense.