NASM - The Netwide Assembler
NASM Forum => Using NASM => Topic started by: RagingGrim on December 16, 2014, 05:21:07 PM
-
I'm using a 64 bit version of Windows 7 ultimate.
I wrote a small batch script to make the assembling go a little smoother.
@echo off
color 0a
title NasmWrapper
cls
set /p Name="Enter A Project Name-> "
goto Compile
exit
:Compile
title Compiling
nasm -f win32 Projects\%Name%\%Name%.asm -o Projects\%Name%\%Name%.o
H:\MinGW\bin\ld Projects\%Name%\%Name%.o -o Projects\%Name%\%Name%.exe
echo Press Enter To Compile Again
echo Enter Exit To Quit
echo Enter Debug To Test.
set /p Choice=
if "%Choice%"=="Exit" (goto Exit)
if "%Choice%"=="Debug" (goto Debug)
goto Compile
:Debug
title Debugging
set %ErrorLevel% = "0"
start Projects\%Name%\%Name%.exe
echo Process Returned With Errorlevel : %ErrorLevel%
echo Press Enter To Test Again
echo Or Compile To Recompile
set /p Choice=
if "%Choice%"=="Exit" (
goto Exit)
if "%Choice%"=="Compile" (
goto Compile)
goto Debug
:Exit
cls
echo Closing...
pause
I tried this bit of code ( random guessing XD )
start:
JMP loop
ret 0
loop:
JMP loop
So it works fine. Opens the console and keeps it open and all. I know the ret call is never reached. I've been searching since last night and I just can't find any working examples of basic console program for windows using nasm. How do i output to the screen using the winapi? I understand i have to use the extern keyword followed by a function name and then with "ld" use the -l/*LibraryName*/ to use functions. I suppose it would be the same if I tried to use functions in the winapi.
I also had a nice little program I wrote in C that used nasm but I deleted that last night after I decided the trouble wasn't worth the reward.
I'm eager to learn. Please help ^^
-
Please report trouble. I could test it only on WinXP.
; Name: hello.asm
; Assemble: nasm.exe -fwin32 hello.asm
; Link: ld hello.obj -emain -lkernel32 --enable-stdcall-fixup %SYSTEMROOT%\system32\kernel32.dll
; Run: a.exe
BITS 32
extern _GetStdHandle
extern _WriteFile
extern _ExitProcess
SECTION .data
str: db "Hello world!"
strlen equ $-str
SECTION .text
GLOBAL main
main:
; Stack frame for NumberOfBytesWritten
push ebp
sub esp, 4
; http://msdn.microsoft.com/en-us/library/windows/desktop/ms683231.aspx
; HANDLE WINAPI GetStdHandle(
; _In_ DWORD nStdHandle
; );
push -11
call _GetStdHandle
; http://msdn.microsoft.com/en-us/library/windows/desktop/aa365747.aspx
; BOOL WINAPI WriteFile(
; _In_ HANDLE hFile,
; _In_ LPCVOID lpBuffer,
; _In_ DWORD nNumberOfBytesToWrite,
; _Out_opt_ LPDWORD lpNumberOfBytesWritten,
; _Inout_opt_ LPOVERLAPPED lpOverlapped
; );
push 0 ; lpOverlapped,
lea ebx, [ebp-4] ; EBX: address of NumberOfBytesWritten
push ebx ; lpNumberOfBytesWritten,
push strlen ; nNumberOfBytesToWrite
push str ; lpBuffer,
push eax ; hFile (result from GetStdHandle
call _WriteFile
; ExitProcess (0)
push 0
call _ExitProcess
viele grüße
ralph
-
Thanks Ralph
The Errors I get are all undefined references to those functions.
Undefined reference to GetStdHandle,WriteFile and ExitProcess.
Sorry! Missed the link options :O
It works fine if i compile it with the additional params ^^
Could you maybe explain this to me? I get the general idea but i'd like to know more ^^
I had to insert this
JMP loop
ret 0
loop:
JMP loop
To get my program to pause :P there must be a better way?
-
Hi RagingGrim,
Good to see you here! I saw your question at SO the other day, and was going to suggest that we might have some examples in the "Examples" section (duh!). Turns out that we don't have a simple console example. We should!
I haven't touched Windows since Win98, but digging through the dusty archives I came up with this. As I recall, it "worked", but it is not correct!
; nasm -f win32 hw32cons.asm
; link /entry:start /subsystem:console hw32cons.obj <wherever>\kernel32.lib
%define ExitProcess _ExitProcess@4
%define WriteFile _WriteFile@20
global _start
extern ExitProcess
extern WriteFile
section .text
_start:
push dword 0
push dword num_chars
push dword MSGLEN
push dword msg
push dword -11
call WriteFile
exit_ok: push dword 0
exit: call ExitProcess
section .data
num_chars dd 0
msg db 'Hello, Console.', 13, 10
MSGLEN equ $ - msg
I think the correct way to do it is:
; nasm -f win32 hw32cons.asm
; link /entry:start /subsystem:console hw32cons.obj <wherever>\kernel32.lib
%define ExitProcess _ExitProcess@4
%define GetStdHandle _GetStdHandle@4
%define WriteFile _WriteFile@20
global _start
extern ExitProcess
extern GetStdHandle
extern WriteFile
section .text
_start:
push -11 ; defined as "STDIN" somewhere, no doubt
call GetStdHandle
; should return our handle in eax
push dword 0
push dword num_chars
push dword MSGLEN
push dword msg
push eax
call WriteFile
exit_ok: push dword 0
exit: call ExitProcess
section .data
num_chars dd 0
msg db 'Hello, Console.', 13, 10
MSGLEN equ $ - msg
That's untested, but I think it "should work".
I am unable to advise what the command line to ld should be. I think I got it to work (using Cygwin, not MinGW) by pointing it to a library I got from Hutch's "MASM32" package once...
The NASMX package - http://nasmx.sf.net - contains some macros and a lot of "%defines" and examples, but I don't think it has any actual libraries. It uses Golink rather than ld, and in that case we can just list the .dlls we need on the command line. Perhaps MinGW includes the libraries you need? (Might need to use the uppercase "-L/path/to/library" switch as well as the "-l thelib" switch?)
I apologize for not having a better answer for you. I'm pretty stubborn about "I don't use Windows anymore" (not even Wine). Maybe someone can provide a "known to work" example. Seems like a simple enough request...
Best,
Frank
Well, I see Ralph has posted a "better" example. Good luck!
-
Could you maybe explain this to me? I get the general idea but i'd like to know more ^^
--enable-stdcall-fixup is a MinGW-Windows-issue. You can find an explanation in the official manual of ld: https://sourceware.org/binutils/docs/ld/Options.html#Options (https://sourceware.org/binutils/docs/ld/Options.html#Options). Short: without that option you have to use _GetStdHandle@4, _WriteFile@20, _ExitProcess@4 and so on for every WinAPI function. I will show it in the following example.
-emain determines the procedure named main as entry point.
-lkernel32 forces LD to look for a library called libkernel32.a. There it can find further "hints" for calling the functions of kernel32.dll.
To get my program to pause :P there must be a better way?
There are many ways. I'll show you a way that uses the MS-C-library (msvcrt.dll):
; Name: hello.asm
; Assemble: nasm.exe -fwin32 hello.asm
; Link: ld hello.obj -emain -lkernel32 -lmsvcrt
; Run: a.exe
BITS 32
extern _GetStdHandle@4
extern _WriteFile@20
extern _ExitProcess@4
extern __getch
extern _puts
SECTION .data
str: db `Hello world!\n` ; C-like strings in NASM with backticks
strlen equ $-str
pause: db "Do you know where the ANY key is? :-)",0
SECTION .text
GLOBAL main
main:
; Stack frame for NumberOfBytesWritten
push ebp
sub esp, 4
; http://msdn.microsoft.com/en-us/library/windows/desktop/ms683231.aspx
; HANDLE WINAPI GetStdHandle(
; _In_ DWORD nStdHandle
; );
push -11
call _GetStdHandle@4
; http://msdn.microsoft.com/en-us/library/windows/desktop/aa365747.aspx
; BOOL WINAPI WriteFile(
; _In_ HANDLE hFile,
; _In_ LPCVOID lpBuffer,
; _In_ DWORD nNumberOfBytesToWrite,
; _Out_opt_ LPDWORD lpNumberOfBytesWritten,
; _Inout_opt_ LPOVERLAPPED lpOverlapped
; );
push 0 ; lpOverlapped,
lea ebx, [ebp-4] ; EBX: address of NumberOfBytesWritten
push ebx ; lpNumberOfBytesWritten,
push strlen ; nNumberOfBytesToWrite
push str ; lpBuffer,
push eax ; hFile (result from GetStdHandle
call _WriteFile@20
; msvcrt.dll (C library)
push pause
call _puts ; http://msdn.microsoft.com/library/tf52y4t1.aspx
add esp, 4
call __getch ; http://msdn.microsoft.com/library/078sfkak.aspx
; ExitProcess (0)
push 0
call _ExitProcess@4
viele grüße
ralph
-
Thanks for all the replies!
Would it be a good idea to play around with these functions in an easier language before i start using them in assembly? I have a C compiler and I'm comfortable with the language ^^
BITS 32
extern _GetStdHandle
extern _ExitProcess
extern _WriteFile
section .Text
GLOBAL main
main:
mov eax,3
ret 0
I was just messing around with trying to create a skeleton from memory so the mov eax,3 is just random. But it triggers my antivirus XD Is there any specific reason for that because mov eax,5 does not XD
-
I'm really into assembly ! I even got myself a book to make notes in XD
Not even C deserved a book...XD
So I was wondering what would happen if I repeatedly pop a register which is not on the stack. I tried this and my program crashed.
Then I tried pushing eax onto the stack before popping it and BAM - no crash.
My conclusion was that when you attempt to pop a register which is not currently on the program's stack your program will crash ( in a windows environment ). Would I be correct?
-
So I was wondering what would happen if I repeatedly pop a register which is not on the stack. I tried this and my program crashed.
Then I tried pushing eax onto the stack before popping it and BAM - no crash.
My conclusion was that when you attempt to pop a register which is not currently on the program's stack your program will crash ( in a windows environment ). Would I be correct?
To understand the reason why your program crashed you need to understand the purpose and layout of the Call Stack (http://en.wikipedia.org/wiki/Call_stack)
Once you have a firm grasp on that you should then study Calling Conventions (http://en.wikipedia.org/wiki/Calling_convention)
-
Once again thanks for all the replies I thought I'd just play around with calling kernel32 instructions. ^^ I went with beep as my victim :p
BITS 32
extern _Beep
global main
section .TEXT
main:
push 500
push 3000
call _Beep
add ebp,8 ;4*2
push 503
push 3003410
call _Beep
add ebp,8 ;4*2
ret
Code works fine and it beeps and all that. I was just curious ;After calling the beep function are those values removed from the stack? I read something about adding 4*NumberOfParams to the ebp register to clear the stack? Something like that?
Also if I do this:
BITS 32
extern _Beep
global main
section .TEXT
main:
push 500
push 3000
call _Beep
call _Beep
ret
The first beep would obviously execute fine but what about the second one ? My pc keeps beeping so I assume it's using values from memory that it shouldn't be using ? :O By not clearing the stack ? Is that why this happens?
Thanks!
-
In your first example you are modifying the EBP register rather than the ESP register. Normally, to remove values that you've pushed on the stack you would either POP the values off or "ADD ESP, XX" after the call where XX is the number of bytes pushed prior to the call in order to keep the stack aligned and balanced.
However, for functions which are declared as StdCall in Windows you don't need to do anything after the call since the called function itself will restore the stack using the "ret XX" op-code. This is why I recommend understanding calling conventions in order to know 1.) how the caller expects parameters to appear on the stack; and 2.) who's responsible for restoring the stack - the caller or the callee.
-
Just a quicky, picky, comment besides what Rob has mentioned. "section .TEXT" - Nasm's keywords are generally case insensitive. You can say "section" or "SECTION" or "segment" or "SEGMENT" - all the same to Nasm. However, the "known names" - ".text", ".data", ".bss", etc. are case sensitive. In Windows output formats, "arbitrary names" are treated like ".text", so it won't do any harm. But "section .DATA" would also be treated like ".text" - that is, readonly. Since "section .data" is expected to be writable, this could cause a confusing error. Just thought I'd mention it...
Best,
Frank
-
Thanks Rob , I read the bit about the callee and the caller . I made a note about it under C Language Calling Convention ( I think I got it from a x86 Assembly Tutorial I found somewhere ) , I haven't memorised all of it just yet because I'm trying not to bore myself with all the theory just yet :P But I'll make a point of learning more theory everyday ^^
Thanks to you too Frank :P I don't understand what you said completely but maybe that's just my english. I'll read up more and look into the nasm manual as well. I guess I mean I get it..but I don't?
Thanks All!