NASM - The Netwide Assembler
NASM Forum => Programming with NASM => Topic started by: NASM on September 12, 2018, 11:20:36 AM
-
Help me pls import function
BITS 64
SECTION .bss
hSocket: resq 1
SECTION .data
port: equ 777
struc WSADATA
.wVersion: resw 1
.wHighVersion: resw 1
.szDescription: resb 256
.szSystemStatus: resb 256
.iMaxSockets: resd 1
.iMaxUdpDg: resd 1
.lpVendorInfo: resq 1
endstruc
struc sockaddr_in
.sin_family: resd 1
.sin_port: resd 1
.sin_addr: resq 1
.sin_zero: resb 8
.size:
endstruc
SECTION .text
global start
extern WSAStartup
extern WSACleanup
extern socket
extern Sleep
extern ExitProcess
import ExitProcess kernel32.dll
extern accept
extern listen
extern bind
start:
mov rdx , [WSADATA]
mov rcx , 0x202
call WSAStartup
mov r8 , 0
mov rdx , 1
mov rcx , 2
call socket
mov [hSocket] , rax
mov dword [sockaddr_in.sin_family] , 1
mov qword [sockaddr_in.sin_addr] , 0
mov ax , port
xchg ah , al
mov [sockaddr_in.sin_port] , ax
mov r8 , sockaddr_in.size
mov rdx , [sockaddr_in]
mov rcx , hSocket
call bind
mov rdx , 13
mov rcx , hSocket
call listen
mov r8 , 0
mov rdx , [sockaddr_in]
mov rcx , hSocket
call accept
mov rcx , 60000
call Sleep
call WSACleanup
mov rcx,0
call ExitProcess
C:\msys64\home\Alexey>nasm cmd.asm -f win64 -o cmd.obj
cmd.asm:39: error: parser: instruction expected
https://wasm.in/threads/lld-bsd-exe.32375/#post-402921
-
There is no "import" directive in NASM... All symbols resolution is made in linking phase...
-
LLD BSD EXE (https://wasm.in/threads/lld-bsd-exe.32375/#post-404041")
Wont write clear browser wif support MSHTML.DLL
WASM.IN FORUM
-
I still do not understand how to import functions?
(https://pp.userapi.com/c846416/v846416039/17a74f/OU9Exp0LcD0.jpg)
pexports C:\Windows\System32\user32.dll > user32.def
dlltool -d user32.def -l user32.lib
-
Import is not a processor directive, it is a macro that generates a series of commands, and it is not part of nasm. If you really need to use it, you will need MASM.
-
Win32 or Win64 API functions are aliases to the real names, that always end with A or W. The real function name of WSAStartup is WSAStartupA or WSAStartupW.
And you must statically link the DLL surrogate library or load it dinamycally with LoadLibraryA (or LoadLibraryW)...
-
Here's an example (Win32):
; winapp.asm
; NASM code to simple Hello Windows!
bits 32
%include "win32.inc"
section .data
winapp_class: db "MyWinAppClass",0
winapp_title: db "My Windows App",0
msg_caption: db "Error",0
msg_text: db "Error creating main window.",0
wc: istruc WNDCLASS
at WNDCLASS.style, dd (CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS)
at WNDCLASS.hbrBackground, dd (COLOR_WINDOW+1)
iend
msg: istruc MSG
iend
section .bss
hWnd: resd 1
section .text
; Imported from kernel32.exe & user32.exe
extern __imp__LoadIconA@8
extern __imp__LoadCursorA@8
extern __imp__RegisterClassA@4
extern __imp__CreateWindowExA@48
extern __imp__MessageBoxA@16
extern __imp__UpdateWindow@4
extern __imp__ShowWindow@8
extern __imp__GetMessageA@16
extern __imp__TranslateMessage@4
extern __imp__DispatchMessageA@4
extern __imp__DefWindowProcA@16
extern __imp__PostQuitMessage@4
global _WindowMessagesHandler@16
struc WndMsgHandlerStk
.oldebp: resd 1
.retaddr: resd 1
.hWnd: resd 1
.uMsg: resd 1
.wParam: resd 1
.lParam: resd 1
.size:
endstruc
WNDMSGHANDLERSTKSIZE equ WndMsgHandlerStk.size - WndMsgHandlerStk.hWnd
align 16
_WindowMessagesHandler@16:
push ebp
mov ebp,esp
cmp dword [ebp + WndMsgHandlerStk.uMsg],WM_DESTROY
jz Handle_Destroy
push dword [ebp + WndMsgHandlerStk.lParam]
push dword [ebp + WndMsgHandlerStk.wParam]
push dword [ebp + WndMsgHandlerStk.uMsg]
push dword [ebp + WndMsgHandlerStk.hWnd]
call dword [__imp__DefWindowProcA@16]
jmp HandlerExit
Handle_Destroy:
push dword 0
call dword [__imp__PostQuitMessage@4]
xor eax,eax
HandlerExit:
pop ebp
ret WNDMSGHANDLERSTKSIZE
global _WinMain@16
struc WinMainStk
.oldebp: resd 1
.retaddr: resd 1
.hInstance: resd 1
.hPrevInstance: resd 1
.lpszCmdLine: resd 1
.nCmdShow: resd 1
.size:
endstruc
WINMAINSTKSIZE equ WinMainStk.size - WinMainStk.hInstance
align 16
_WinMain@16:
push ebp
mov ebp,esp
;-----------------
; Registra a classe de janela.
;-----------------
mov eax,[ebp+WinMainStk.hInstance]
mov [wc+WNDCLASS.hInstance],eax
push dword IDI_APPLICATION
push dword 0
call dword [__imp__LoadIconA@8]
mov [wc+WNDCLASS.hIcon],eax
push dword IDC_ARROW
push 0
call dword [__imp__LoadCursorA@8]
mov [wc+WNDCLASS.hCursor],eax
mov eax,_WindowMessagesHandler@16
mov [wc+WNDCLASS.lpWndProc],eax
mov eax,winapp_class
mov [wc+WNDCLASS.lpszClassName],eax
push wc
call dword [__imp__RegisterClassA@4]
;-----------------
; Cria a nova janela.
;-----------------
push dword 0
push dword [ebp+WinMainStk.hInstance]
push dword 0
push dword 0
push dword 480
push dword 640
push dword CW_USEDEFAULT
push dword CW_USEDEFAULT
push dword WS_OVERLAPPEDWINDOW
push winapp_title
push winapp_class
push dword 0
call dword [__imp__CreateWindowExA@48]
test eax,eax
jnz created_ok
;----
; Em caso de erro com CreateWindowEx...
;----
push dword (MB_OK | MB_ICONERROR)
push msg_caption
push msg_text
push dword 0
call dword [__imp__MessageBoxA@16]
xor eax,eax
jmp WinMainExit
;----
; Tudo ocorreu bem com CreateWindowEx...
;----
created_ok:
mov [hWnd],eax ; Salva o handle.
;---- Update and Show...
push eax
call dword [__imp__UpdateWindow@4]
push dword [ebp+WinMainStk.nCmdShow]
push dword [hWnd]
call dword [__imp__ShowWindow@8]
MessageLoop:
push dword 0
push dword 0
push msg
push dword [hWnd]
call dword [__imp__GetMessageA@16]
test eax,eax
jz ExitLoop
push msg
call dword [__imp__TranslateMessage@4]
push msg
call dword [__imp__DispatchMessageA@4]
jmp MessageLoop
ExitLoop:
mov eax,[msg+MSG.wParam]
WinMainExit:
pop ebp
ret WINMAINSTKSIZE
The include file:
; win32.inc
%define CS_VREDRAW 1
%define CS_HREDRAW 2
%define CS_DBLCLKS 8
%define COLOR_WINDOW 5
%define WM_DESTROY 2
%define IDI_APPLICATION 32512
%define IDC_ARROW 32512
%define CW_USEDEFAULT 0x80000000
%define WS_OVERLAPPED 0x000000
%define WS_CAPTION 0xc00000
%define WS_SYSMENU 0x080000
%define WS_THICKFRAME 0x040000
%define WS_MINIMIZEBOX 0x020000
%define WS_MAXIMIZEBOX 0x010000
%define WS_OVERLAPPEDWINDOW (WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX)
%define MB_OK 0
%define MB_ICONERROR 0x10
struc WNDCLASS
.style: resd 1
.lpWndProc: resd 1
.cbClsExtra: resd 1
.cbWndExtra: resd 1
.hInstance: resd 1
.hIcon: resd 1
.hCursor: resd 1
.hbrBackground: resd 1
.lpszMenuName: resd 1
.lpszClassName: resd 1
endstruc
struc MSG
.hWnd: resd 1
.message: resd 1
.wParam: resd 1
.lParam: resd 1
.time: resd 1
.pt: resd 2
endstruc
The makefile:
; Makefile
CC=i686-w64-mingw32-gcc
.PHONY: all clean
all: winapp.exe
winapp.exe: winapp.o
$(CC) -O3 -s -o $@ $^
winapp.o: winapp.asm win32.inc
nasm -f win32 -o $@ $<
clean:
-rm *.o
Compiled with 'make', using mingw32 (linux).
libkernel32.a, libuser32.al and libgdi32.al are linked by default, but winsock2.dll must be linked adding-lws2_32.
The static surrogate libraries to DLLs are in /usr/i686-w64-minw32/. Take a look at them with objdump -x <libfile>.
-
Of course, for Win64 the calling convention is different and the functions naming are different (there is no @N at the end and the prefix is '__imp_' - with a single '_'). And all Win API function calls are always indirect...
-
Ok... the same example for Win64 using mingw64:
Sorry, there are some comments in portuguese (pt_BR)...
; winapp.asm
; NASM code for win64
bits 64
default rel
%include "win64.inc"
section .data
winapp_class: db `MyWinAppClass\0`
winapp_title: db `My Windows App\0`
msg_caption: db `Error\0`
msg_text: db `Error creating main window.\0`
wc: istruc WNDCLASS
at WNDCLASS.style, dd (CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS)
at WNDCLASS.hbrBackground, dd (COLOR_WINDOW+1)
iend
msg: istruc MSG
iend
section .bss
hWnd: resd 1
nCmdShow: resd 1
section .text
; Imported from kernel32.exe & user32.exe
extern __imp_LoadIconA
extern __imp_LoadCursorA
extern __imp_RegisterClassA
extern __imp_CreateWindowExA
extern __imp_MessageBoxA
extern __imp_UpdateWindow
extern __imp_ShowWindow
extern __imp_GetMessageA
extern __imp_TranslateMessage
extern __imp_DispatchMessageA
extern __imp_DefWindowProcA
extern __imp_PostQuitMessage
;===============================
; Win64 calling convention:
; RCX, RDX, R8 and R9 are used for the first 4 arguments,
; any others goes to stack
;===============================
align 16
global _WindowMessagesHandler
; Entry: ECX = hWnd,
; EDX = uMsg
; R8D = wParam
; R9D = lParam (yep... dword).
_WindowMessagesHandler:
cmp edx,WM_DESTROY
jz Handle_Destroy
; All registers are already in place!
call qword [__imp_DefWindowProcA]
ret
Handle_Destroy:
xor ecx,ecx
call qword [__imp_PostQuitMessage]
xor eax,eax
HandlerExit:
ret
align 16
global WinMain
; Entry: ECX = hInstance,
; EDX = hPrevInstance
; R8 = lpszCmdLine
; R9D = nCmdShow
WinMain:
;-----------------
; Registra a classe de janela.
;-----------------
mov [wc+WNDCLASS.hInstance],ecx
mov [nCmdShow],r9d ; salva nCmdShow
xor ecx,ecx
mov edx,IDI_APPLICATION
call qword [__imp_LoadIconA]
mov [wc+WNDCLASS.hIcon],eax
xor ecx,ecx
mov edx,IDC_ARROW
call qword [__imp_LoadCursorA]
mov [wc+WNDCLASS.hCursor],eax
lea rax,[_WindowMessagesHandler]
mov [wc+WNDCLASS.lpWndProc],rax
lea rax,[winapp_class]
mov [wc+WNDCLASS.lpszClassName],rax
lea rcx,[wc]
call qword [__imp_RegisterClassA]
;-----------------
; Cria a nova janela.
;-----------------
xor ecx,ecx
lea rdx,[winapp_class]
lea r8,[winapp_title]
mov r9d,WS_OVERLAPPEDWINDOW
; Todos os outros parĂ¢metros na pilha (C style)
push 0
mov eax,[wc+WNDCLASS.hInstance]
push rax
push 0
push 0
push 480
push 640
push CW_USEDEFAULT ; nasm warning: Ignore it!
push CW_USEDEFAULT ; nasm warning: Ignore it!
call qword [__imp_CreateWindowExA]
test eax,eax
jnz created_ok
;----
; Em caso de erro com __imp_CreateWindowEx...
;----
xor ecx,ecx
lea rdx,[msg_text]
lea r8,[msg_caption]
mov r9d,(MB_OK | MB_ICONERROR)
call qword [__imp_MessageBoxA]
xor eax,eax
jmp WinMainExit
;----
; Tudo ocorreu bem com __imp_CreateWindowEx...
;----
created_ok:
mov [hWnd],eax ; Salva o handle.
;---- __imp_Update and Show...
mov ecx,eax
call qword [__imp_UpdateWindow]
mov ecx,[hWnd]
mov edx,[nCmdShow]
call qword [__imp_ShowWindow]
MessageLoop:
mov ecx,[hWnd]
lea rdx,[msg]
xor r8d,r8d
xor r9d,r9d
call qword [__imp_GetMessageA]
test eax,eax
jz ExitLoop
lea rcx,[msg]
call qword [__imp_TranslateMessage]
lea rcx,[msg]
call qword [__imp_DispatchMessageA]
jmp MessageLoop
ExitLoop:
mov eax,[msg+MSG.wParam]
WinMainExit:
ret
Notice that our functions don't deal with the stack (they have 4 arguments, allocated on RCX, RDX, R8 and R9 only)... This allow us to use a simple RET... Only pointers must be 8 bytes long. Handles are still DWORDs (Win64 uses IL32P64 standard)... When we have to put arguments on stack (before calling CreateWindowExA), this must be done in C style (last argument first), but the 4 first arguments must (if integers) must be passed on RCX,RDX,R8 and R9 registers.
All Win64 API calls are still indirect...
; win64.inc
%define CS_VREDRAW 1
%define CS_HREDRAW 2
%define CS_DBLCLKS 8
%define COLOR_WINDOW 5
%define WM_DESTROY 2
%define IDI_APPLICATION 32512
%define IDC_ARROW 32512
%define CW_USEDEFAULT 0x80000000
%define WS_OVERLAPPED 0x000000
%define WS_CAPTION 0xc00000
%define WS_SYSMENU 0x080000
%define WS_THICKFRAME 0x040000
%define WS_MINIMIZEBOX 0x020000
%define WS_MAXIMIZEBOX 0x010000
%define WS_OVERLAPPEDWINDOW (WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX)
%define MB_OK 0
%define MB_ICONERROR 0x10
struc WNDCLASS
.style: resd 1
.lpWndProc: resq 1 ; ptrs are 8 bytes long.
.cbClsExtra: resd 1
.cbWndExtra: resd 1
.hInstance: resd 1
.hIcon: resd 1
.hCursor: resd 1
.hbrBackground: resd 1
.lpszMenuName: resq 1 ; ptrs are 8 bytes long.
.lpszClassName: resq 1 ; ptrs are 8 bytes long.
endstruc
struc MSG
.hWnd: resd 1
.message: resd 1
.wParam: resd 1
.lParam: resd 1
.time: resd 1
.pt: resd 2
endstruc
# Makefile
CC=x86_64-w64-mingw32-gcc
.PHONY: all clean
all: winapp.exe
winapp.exe: winapp.o
$(CC) -O3 -s -o $@ $^
# -f win64 is necessary!
winapp.o: winapp.asm win64.inc
nasm -f win64 -o $@ $<
clean:
-rm *.o
When using winsock2 you have to declare __imp_WSAStartup (no A or W, 'cause there are no string arguments) as external, use RCX and RDX as arguments and call it indirectly... You have also to link libwsock32 adding -lwsock32 to the linker.