NASM - The Netwide Assembler
NASM Forum => Programming with NASM => Topic started by: Duck on August 27, 2021, 04:40:57 AM
-
i am new to nasm and i trying to print a number in windows but i can't :(
i don't want to use constants or printf
global _main
extern _GetStdHandle@4
extern _WriteFile@20
extern _ExitProcess@4
section .text
_main:
; DWORD bytes;
mov ebp, esp
sub esp, 4
mov DWORD [ebp-4], 10
push -11
call _GetStdHandle@4
mov ebx, eax
push 0
push DWORD [ebp-4]
lea eax, [ebp-8]
push eax
push (message_end - message)
push message
push ebx
call _WriteFile@20
push 0
call _ExitProcess@4
hlt
message:
db "%d", 10
message_end:
help me please...
please :(
-
I've never programmed for Windows, but don't you need to include a .inc file (equivalent to a C header file) so nasm or your linker know where the routines you are calling are located?
-
but don't you need to include a .inc file
not that i know, the truth, the following code works without problems
global _main
extern _GetStdHandle@4
extern _WriteFile@20
extern _ExitProcess@4
section .text
_main:
mov ebp, esp
sub esp, 4
push -11
call _GetStdHandle@4
mov ebx, eax
push 0
lea eax, [ebp-4]
push eax
push (message_end - message)
push message
push ebx
call _WriteFile@20
push 0
call _ExitProcess@4
hlt
message:
db 'Hello, World', 10
message_end:
but the problem is that there the "hello word" is declared globally, that is, it is constant, i need it to be reserved in memory at runtime, not as constant if not using mov DWORD [ebp-4], 10
it has been very difficult for me to get info for windows, i know that it is easier and better for linux, but i need it for windows. :(
-
Use console API (not WriteFile). hello_win.asm (Windows x64), hello_win32.asm (Windows x86).
-
If you need to print a string you'll need to pass the size of this string or, at least, use C style strings and put a NULL char at the and to get this size:
; Entry RDI - pointer to char
; Exit: EAX, size of string
; Destroys RDI.
strlen_:
xor eax,eax
.loop:
cmp byte [rdi],0
je .exit
inc eax
inc rdi
jmp .loop
.exit:
ret
; Entry ECX = stdout handle. RDX = pointer to string.
; Destroys RDI, R8 and R9.
printstr:
sub rsp,40 ; Win64 calling convetion reserves 32 bytes on stack (will reserve 8 bytes more)
mov rdi,rdx
call strlen_
mov r8d,eax
mov r9,rsp
push 0
call [__imp_WriteConsoleA]
add rsp,40
ret
Usage:
section .data
msg: db 'hello', 0
section .text
...
; rcx must have the stdout handle
lea rdx,[msg]
call printstr
-
Now... if you want to allocate memory use VirtualAlloc() and VirtualFree() Win API functions. They are well documented in MSDN. Tip, as you can see the name of the 'stub' library used to call this functions from kernel32.dll are prefixed and suffixed (in 32 bits mode only) differently, accordingly to the mode used: x86-64 use __imp_ prefix only and i386 mode use prefix __imp__ and sufixed with @N, where N is the number of bytes of the arguments, pushed to the stack.
So, to allocate 128 bytes of memory in i386 mode you must do:
; allocate 128 bytes
push 0 ; NULL.
push 128 ; sizeof of requested block.
push 0x1000 ; MEM_COMMIT
push 4 ; PAGE_READWRITE
call [__imp__VirtualAlloc@16]
; EAX has the address of buffer allocated.
mov [allocaddr],eax ; save it.
; It is prudent to call VirtualLock here.
push eax
push 128 ; size
call [__imp__VirtualLock@8]
...
; deallocate buffer
push [allocaddr]
push 128 ; size
call [__imp__VirtualUnlock@8]
push [allocaddr]
push 0 ; size (must be 0 to release memory).
push 0x8000 ; MEM_RELEASE
call [__imp__VirtualFree@12]