import in NASM doesn't work? - windows

i'm trying to compile the following code on windows 7 (with NASM):
[BITS 32]
extern ExitProcess
import ExitProcess kernel32.dll
extern MessageBoxA
import MessageBoxA user32.dll
segment .data use32
Caption db 'Caption Text',0
Text db "My MessageBox Text.",0
segment .code use32
..start:
push dword 0
push dword Caption
push dword Text
push dword 0
call [MessageBoxA]
push dword 0
call [ExitProcess]
To compile this, I tried nasm -o test.o test.asm, but then it says:
test.asm:4: error: parser: instruction expected
test.asm:6: error: symbol `import' redefined
test.asm:6: error: parser: instruction expected
Why doesn't it work?
EDIT: ok. simple mistake... nasm -o test.o -f obj test.asm works...

Seems like a known problem. Resolution suggested in http://cboard.cprogramming.com/windows-programming/114989-nasm-import-directive-failing-expected-instruction-error.html

You should not have to use Obj. That is meant for DOS not Windows. Yes, you can use a ton of compiler directives in your ASM code to make it work in Windows, but if you compile with type Win32, you will end up with code specifically that works in Windows. Unfortunately whoever wrote NASM worte it in such a way that import doesn't work in Win32 mode (even though it should, as import is a very standard, and required operation for working in Windows). And even MORE unfortunately is that the person who wrote NASM seems to have stopped adding/improving/upgrading the program and has basically abandoned the project. And with no way for the community to fix this bug our selves (the source code for NASM isn't publicly available), that leaves us with a HUGELY DEFECTIVE PRODUCT!

Related

How can I debug executables for Windows using GDB in WSL?

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.

Compiling error whilst using command from NASM and mingw

I want to play a bit with assembly. To get started I've created a little asm script and tried to compile it. In the first step everything went great:
nasm -felf64 hello.asm
But when I tried to use
ld -o hello.o hello
from MinGW an error occured:
hello.o: file not recognized: File format not recognized
What can I do to fix this problem? I've tried it with gcc as well but then the same error plus one other error occurs.
MinGW creates binaries targeting Windows. Windows does not support ELF binaries (or does it? with Windows subsystem for Linux?). Anyway, ld in MinGW will expect that you provide binaries in win64 format not elf64.
nasm -fwin64 hello.asm will most likely work.
No it won't work because I just saw your code, and you are using Linux syscalls under Windows.
Write,
mov rcx, 69
call ExitProcess
instead of,
mov rax, SYS_EXIT
mov rdi, 69
syscall
Leave a comment if it doesn't work.

File format not recognized when trying build an exe from obj in windows

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.

Is it true that .exe can't run without .bss section in 64bit windows?

I came across this problem when I noticed some of my old programs failed to run under modern Windows.
Here is a miniature example, built via mingw64
.text
.global start
start:
subq $0x48,%rsp
xorl %ecx,%ecx
call *__imp_ExitProcess(%rip)
addq $0x48,%rsp
ret
gcc a.s -nostdlib -nostartfiles -lkernel32 -Wl,-e,start,-s
A message box says the exe is not valid Win32 program when I open it. However the program runs successfully when I add .lcomm a,1 or
.bss
.int 0
to the source file, both effectively inserting .bss section into the exe file. Adding .data section does not solve the problem.
Is this an inherent restriction of Windows or a bug inside ld?
EDIT:
Ok. I've found many exe files without .bss or any section with uninitialized data but run well nevertheless. But this does not fully answer my question. Why my program with only .data , .text and .idata unable to run?
EDIT V2:
I think I have found the cause. The value of OptionalHeader.SizeOfImage is incorrect. Changing it to correct value solves the problem. So this is most likely a bug inside ld.

x86 assembly create Win32 executable NASM

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.

Resources