I'm using nasm to compile the following assembly. However the code crashes in the console under Windows.
C:\>nasm -f win32 test.asm -o test.o
C:\>ld test.o -o test.exe
section .data
msg db 'Hello world!', 0AH
len equ $-msg
section .text
global _WinMain#16
_WinMain#16:
mov edx, len
mov ecx, msg
mov ebx, 1
mov eax, 4
int 80h
mov ebx, 0
mov eax, 1
int 80h
According to this post. The main function is not available under Windows and must be replaced by WinMain.
So if your entry point is _start or main, it should be changed to _WinMain#16 and change the ret at the end of the procedure to ret 16:
My working example:
section .text
global _WinMain#16
_WinMain#16:
mov eax, 0
ret 16
The biggest problem is that you are trying to use Linux interupts on windows!
int 80 will NOT work on windows.
We are using Assembly, so your entry point can be ANY label you want. The standard entry point that ld looks for is _start, if you want to use another label, you need to tell ld with the -e option
So if you want your start label to be main, then you need
global main
ld -e main test.o -o test.exe
If you are going to use NASM on Windows, I will recommend using GoLink as your linker.
Here is a simple windows console app:
STD_OUTPUT_HANDLE equ -11
NULL equ 0
global GobleyGook
extern ExitProcess, GetStdHandle, WriteConsoleA
section .data
msg db "Hello World!", 13, 10, 0
msg.len equ $ - msg
section .bss
dummy resd 1
section .text
GobleyGook:
push STD_OUTPUT_HANDLE
call GetStdHandle
push NULL
push dummy
push msg.len
push msg
push eax
call WriteConsoleA
push NULL
call ExitProcess
makefile:
hello: hello.obj
GoLink.exe /console /entry GobleyGook hello.obj kernel32.dll
hello.obj: hello.asm
nasm -f win32 hello.asm -o hello.obj
Although, this same program probably will run in WINE on Linux like a charm. :)
WINE doesn't prevent using Linux system calls from inside Windows PE binaries; the machine instructions run natively and WINE only provides DLL functions.
Related
I am learning to code assembly (NASM). But i have problem, i am coding online but i want to convert this code below to exe and run it. (By clicking double click on it, not in cmd). And i dont have a clue how to do it. i know i must use a nasm from https:://www.nasm.us and a linker. For the linker i want to use ld from mingw. but i dont know how to do it. i didnt find any thing on the internet
section .data
msg: db "Eneter your name : ", 10
msg_l: equ $-msg
hello: db "Hello, "
hello_l: equ $-hello
section .bss
name: resb 255
section .text
global _start:
_start:
mov eax, 4
mov ebx, 1
mov ecx, msg
mov edx, msg_l
int 80h
mov eax, 3
mov ebx, 0
mov ecx, name
mov edx, 255
int 80h
mov eax, 4
mov ebx, 1
mov ecx, hello
mov edx, hello_l
int 80h
mov eax, 4
mov ebx, 1
mov ecx, name
mov edx, 255
int 80h
mov eax, 1
mov ebx, 0
int 80h
The best way to work with linux in windows is to use wsl2. The windows subsystem will allow you to use real linux system calls. There is a learning curve but its worth it.
Follow a guide on how to install ws2.
Go to the windows store and download one of the few linux terminals. I use ubuntu.
Install gcc in the terminal so that you will have a gnu compiler, gnu assembler, and the gnu linker(ld).
Install nasm in the terminal. Not the windows app version.
After everything is set up, you can get a nice workflow going.
you would open the terminal.
change directories which will get you into the c drive: cd /mnt/c
create a folder in the c drive where you want to do your work
change directories to that folder: cd foldername
create a nasm asm file and put some code into it.
then you can use nasm to assemble, ld to link, execute
When you assemble with nasm you can now use elf:
nasm -f elf32 main.asm
ld -m elf_i386 main.o -o main
./main
or:
nasm -f elf64 main.asm
ld main.o -o main
./main
There is an example code in this introduction, like below:
; Sample x64 Assembly Program
; Chris Lomont 2009 www.lomont.org
extrn ExitProcess: PROC ; external functions in system libraries
extrn MessageBoxA: PROC
.data
caption db '64-bit hello!', 0
message db 'Hello World!', 0
.code
Start PROC
sub rsp,28h ; shadow space, aligns stack
mov rcx, 0 ; hWnd = HWND_DESKTOP
lea rdx, message ; LPCSTR lpText
lea r8, caption ; LPCSTR lpCaption
mov r9d, 0 ; uType = MB_OK
call MessageBoxA ; call MessageBox API function
mov ecx, eax ; uExitCode = MessageBox(...)
call ExitProcess
Start ENDP
End
The above code is inside hello.asm and on Windows, it can be compiled with:
ml64 hello.asm /link /subsystem:windows /defaultlib:kernel32.lib /defaultlib:user32.lib /entry:Start
I don't have access to Windows and MASM, since I'm on Linux and work with NASM. I think if I compile the code on Linux, I would be able to run it with Wine. But yet, I couldn't figure out how to compile it with NASM on Linux and also I couln't figure out what are the NASM options which are equivalent to the MASM ones. Can anybody help me?
You should have been able to find a nasm syntax hello world. Anyway, here is a quick transcription:
extern ExitProcess
extern MessageBoxA
section .data
caption db '64-bit hello!', 0
message db 'Hello World!', 0
section .text
sub rsp,28h ; shadow space, aligns stack
mov rcx, 0 ; hWnd = HWND_DESKTOP
lea rdx, [message] ; LPCSTR lpText
lea r8, [caption] ; LPCSTR lpCaption
mov r9d, 0 ; uType = MB_OK
call MessageBoxA ; call MessageBox API function
mov ecx, eax ; uExitCode = MessageBox(...)
call ExitProcess
Assemble using nasm -f win64 hello.asm. You will also need a linker, I used the mingw port as ld hello.obj -lkernel32 -luser32 (let me emphasize this is not the native ld)
Although package names vary from Linux distro to distro, you can do what you are suggesting by installing (or building from source) a mingw-w64 tool chain and the program JWASM. JWASM is a an assembler that is mostly compatible with MASM.
On Debian based distros (including Ubuntu) you should be able to install the prerequisites with:
apt-get install mingw-w64-x86-64-dev binutils-mingw-w64-x86-64 jwasm
With Ubuntu based systems you'll need to prepend the command above with sudo.
You should then be able to assemble and link using something like:
jwasm -win64 hello.asm
x86_64-w64-mingw32-ld hello.o -lkernel32 -luser32 -o hello.exe
The executable should be runnable using wine64
What would the equivalent nasm would be in windows without using any libraries?
section .text
global _start
_start:
mov edx,len
mov ecx,msg
mov ebx,1
mov eax,4
int 0x80
mov eax,1
int 0x80
section .data
msg db 'Hello, world!', 0xa
len equ $ - msg
I read that _start is replaced with _main in windows but what about the system call? I found this table but im not sure which register gets what argument:
http://j00ru.vexillium.org/syscalls/nt/32/
Im especially confused about how to understand the system calls in windows because in linux its really clear what to do:
https://syscalls.kernelgrok.com/
The documentation for windows assembly, especially the system calls seems really really poor.
I have a simple Hello World program for Windows in pure x86 assembly code that I have compiled and linked with nasm and ld. The problem I am running into is that I can't get DWARF debugging to work. I am using gdb from Mingw64 (i686-posix-dwarf-rev1). This same problem happens if I use gcc to link instead of ld. But, the program builds fine, and if I use STABS debugging, then everything is fine and dandy.
EDIT: Oops, I completely forgot to give the error that gdb shows.
...Dwarf Error: bad offset (0x407000) in compilation unit header (offset 0x0
+ 6) [in module C:\Projects\AsmProjects\HelloWorldWin32\bin\x86\hello32.exe]
(no debugging symbols found)...done
The versions of each program are:
gdb 7.10.1
nasm 2.12.02
ld 2.25
gcc 6.2.0
These are the flags I'm sending to nasm: -f elf32 -Fdwarf -g
These are the flags for gcc link: -o $(BDIR)/x86/$#.exe $^ -L$(Mingw64-x86libs) -lkernel32 -luser32
And these are from ld link:
-mi386pe -o $(BDIR)/x86/$#.exe $^ -L$(Mingw64-x86libs) -lkernel32 -luser32
I have a pretty big makefile, so I'm trying to give the least information that is absolutely neccessary.
Here is the source code for the program:
global _main
extern _GetStdHandle#4
extern _WriteFile#20
extern _ExitProcess#4
section .text
_main:
push ebp
mov ebp,esp
; GetstdHandle( STD_OUTPUT_HANDLE)
push -11
call _GetStdHandle#4
mov ebx, eax
; WriteFile( hstdOut, message, length(message), &bytes, 0);
push 0
push esp
push message_end
push message
push ebx
call _WriteFile#20
; ExitProcess(0)
push 0
call _ExitProcess#4
section .data
message db 'Hello, World',10
message_end equ $ - message
This is not a proper answer but was too long for the comment section.
I compiled on Ubuntu and then ran dwarfdump
It gave an error that may be related to the offset error.
dwarfdump ERROR: dwarf_get_globals: DW_DLE_PUBNAMES_VERSION_ERROR (123)
From a similar error on LLVM, I conclude that the dwarf version information is possibly corrupt or unsupported.
This post indicates that the dwarf information is sensitive to the proper section names. The example appears to have the section names right however.
Have you tried a 64-bit version? Perhaps a clue will appear.
This program appears to work fine Ubuntu. Can you try it on Mingw64?
section .text
global _start ;must be declared for linker (ld)
_start: ;tell linker entry point
mov edx,len ;message length
mov ecx,msg ;message to write
mov ebx,1 ;file descriptor (stdout)
mov eax,4 ;system call number (sys_write)
int 0x80 ;call kernel
mov eax,1 ;system call number (sys_exit)
int 0x80 ;call kernel
section .data
msg db 'Hello, world!',0xa ;our dear string
len equ $ - msg ;length of our dear string
I'm reading a book where all the assembly code examples are written for 32-bit Linux environment, and I'm using a 64-bit Mac. I was able to compile the following program with NASM after changing _start to start. However, when I run the executable it doesn't print hello world as I would expect it to. Is there an option to pass to NASM to compile this in a way that will run on a 64-bit Mac?
I tried:
nasm -f macho32 helloworld.asm
and
nasm -f macho helloworld.asm
followed by:
ld helloworld.o -o helloworld
My code is:
section .data ; data segment
msg db "Hello, world!", 0x0a ; the string and newline char
section .text ; text segment
global start ; Default entry point for ELF linking
start:
; SYSCALL: write(1, msg, 14)
mov eax, 4 ; put 4 into eax, since write is syscall #4
mov ebx, 1 ; put 1 into ebx, since stdout is 1
mov ecx, msg ; put the address of the string into ecx
mov edx, 14 ; put 14 into edx, since our string is 14 bytes
int 0x80 ; Call the kernel to make the system call happen
; SYSCALL: exit(0)
mov eax, 1 ; put 1 into eax, since exit is syscall #1
mov ebx, 0 ; exit with success
int 0x80 ; do the syscall
It's simply not going to work like that. Get a VM and install 32 bit linux in the VM. The problem is not running x86_32 code on x64. The problem is trying the Linux syscall gate on MAC. There's no reason to believe that would work.