Presentation is loading. Please wait.

Presentation is loading. Please wait.

Multi-modules programming

Similar presentations


Presentation on theme: "Multi-modules programming"— Presentation transcript:

1 Multi-modules programming

2 4. Libraries

3 Introduction Library = a separate collection (module) of code and data resources, meant to be reused across multiple programs or by multiple modules of the same program The allowed/contained resources can be subroutines, classes and objects (OO languages), documentation, user manuals, audio and video items etc... Each published resource must be uniquely identifiable They usually have associated unique names but other methods can also be used (such as numerical identifiers) For proper reuse, the behavior and interfaces have to be well documented! User-mode applications are supervised by the OS and can only perform some critical operations through the system libraries Hardware resources: keyboard, disk (files), network, audio/video etc... Software resources: threads, memory and application management etc...

4 Key concepts Linkediting Link-time static linking
Dinamic linking at load-time and run-time Object file formats Relocatable Object Module Format (OMF) A MS-DOS dedicated file format (16 bits) with 32 bits compatibility nasm.exe -fobj și alink.exe Common Object File Format (COFF) A more recent file format embraced by Windows, Unix and EFI Used by Microsoft across the whole build toolchain nasm.exe -fwin32 and link.exe Library types Static libraries (LIB) Import libraries (import LIB) Dynamic libraries (DLL) Relevant nasm directives: global, extern / import and export

5 Key concepts Load-time dynamic linking
The sole information needed by the linker is where the resources are located OMF: their provenience is specified via the NASM directive import COFF: such information is described by an import LIB The resources are not contained inside, it merely provides directions to a DLL The resulting program won’t embed the resources, but instead, it will only reference their names and the library file (.dll) they’re part of The OS (the program loader) is responsible for the actual linking Advantages: Reduced program size Same resources are available to multiple programs without need for duplication Disadvantages: A DLL file is specifically needed as other .obj or .lib files can’t be dynamically linked Complex and time consuming processing is performed right at program start-up Potential version incompatibilities can’t be known beforehand and they’re only detected when trying to run the application

6 Key concepts Runtime dynamic linking
The needed resources are only loaded when explicitly requested and kept for only as long as they’re actually wanted The requests originate on the application side and are handled by the OS Dynamic linking against kernel32.dll is needed at load-time for a handful of essential system subroutines: LoadLibrary: load a DLL at runtime GetProcAddress: search for a resource by its name FreeLibrary: unload and free the DLL resources The linker has no direct involvement throughout the run-time linking process! Advantages: The program starts faster and may need less memory Allows keeping active in memory only the code and data needed for the current activities Behavior can be altered on-the-fly by loading different or updated (DLL) modules Disadvantages: Versioning issues are determined even later, at run-time, and data loss is likely without proper care

7 Key concepts Overview – module inclusion and linking options
Compile-time Link-time Load-time Run-time Static linking Textual inclusion (embedding) OBJ/LIB inclusion (embedding) - Dynamic linking Reference to an external DLL Loading an external DLL How to decide between them? Small ASM-only program? %include is an option, although, it’s not recommended… Self-contained stand-alone program? Static linking is the only way for achieving the result! For every other case dynamic linking is recommended Load-time dynamic linking is easier to use and less error-prone A mix of load-time + run-time dynamic linking should be used for faster application load time and/or for supporting plugin-able application modules or on-the-fly updates

8 Key concepts Overview – the link-editing workflow Stack ...
source 1 obj 1 Stack source 2 / assembler compiler obj 2 librarian static library LIB ... source N obj N static import EXE code + data source 1 obj 1 application EXE uninitialized data Loader source 2 / assembler compiler obj 2 linker ... source N obj N DLL dynamic import at load-time source 1 obj 1 import library LIB ... source 2 / assembler compiler obj 2 linker ... dynamic, run-time import dynamic library DLL source N obj N

9 Using libraries in ASM – the necessary steps
Find the name of the wanted subroutine in the library documentation This applies in the same manner for other resource types too Except for this very first step, which is generic and applies to any resource type, all of the steps that follow are not applicable to anything other than functions! Extract from the function’s documentation the following info: The calling convention The name, type and meaning of each parameter The associated type and meaning of the returned result The file (or files) required for accessing the function, namely: .DLL/.LIB: the dynamic (or static!) library file containing the function .LIB: the import library which is necessary alongside the DLL (for COFF only) .H: although the header files are meant to be used by C programs, due to the rigorous nature of the types and constants definitions contained, it often proves useful even when writing ASM code, and especially so if the documentation doesn’t cover all the technical details an ASM program needs…

10 Using libraries in ASM – the necessary steps
Let the assembler know this is a library function For the OMF only, an import statement is needed to specify the DLL file: Tag the function’s name as being external, having no local implementation Perform the function call The OMF format provides the imported symbols as function pointers, needing to be dereferenced! For the COFF scenario, the imported symbols behave like the usual ASM function labels See Interfacing with high-level languages for more details and the required steps for subroutine calls Important: the function name being used throughout the NASM source code must account for the correct name mangling required (as seen in the multi-module program asm + C example) import function file.dll extern funct call [function] ; like having a function dd function_address var call function ; similar to having a function: ... ASM function

11 Using libraries in ASM – the necessary steps
Assembling the NASM source code OMF: nasm.exe -fobj file.asm COFF: nasm.exe -fwin32 file.asm If there are more files, this command must be issued for each one individually Linking the object files OMF: alink.exe file.obj -oPE -entry start -subsys console Multiple files can be passed all at once, separated by whitespaces COFF: link.exe file.obj library.lib -entry:start -subsystem:console The .lib file corresponds to the import library identified at step 2.d) Any number of import libraries can be specified, separated by space characters For building a library this step is different (see implementing user libraries) Running the application (or using the resulting library) Starting the program: file.exe Debugging: ollydbg.exe file.exe Library: repeat all steps for each new program that’s making use of the library

12 System libraries (Win32)
Purpose: an abstraction layer over the OS and hardware complexity All system libraries are dynamic (DLL files) Offered as part of any standard Windows installation kernel32.dll, user32.dll, ntdll.dll, shell32.dll etc... Operations: In/Out: console, windows, mouse and keyboard, network Process management: create, terminate, change priority Memory management: allocate, free, share, change access rights Files and folders: create, read, write, list, delete Parallel processing: synchronization, threads management ... Similar functionality is offered by other OSes as part of their own (different) system libraries

13 System libraries (Win32) - properties
STDCALL is the usual calling convention for all functions Numeric types: BYTE/WORD/DWORD/QWORD Character strings: LP[C]STR, LP[C]WSTR, LP[C]TSTR C = constant W = wide string (UNICODE), otherwise ANSI/ASCII encoding is implied T = both UNICODE and ASCII forms available (via two different implementations) All strings are NULL terminated (C-like strings) Conventions: The GetLastError() function returns the reason for the last failed operation HANDLE: black-box numerical type associated with some OS-managed resources The CloseHandle() subroutine can (usually) free the resources linked to (identified by) a HANDLE NameA and NameW : the two different implementation of the same function Name, the former being ANSI-friendly while the latter is wide/UNICODE (UTF-16) tailored

14 System libraries (Win32) - File management
The files are seen as devices providing sequential-access to data They have a current position associated, pointing to the next byte to process They don’t necessarily reside on a disk drive and can model other devices too The HANDLE returned when opening a file is needed for any actions CloseHandle is used for freeing resources and saving any changes Path specifier: a string that identifies a unique node in a files and folders tree It defines the folder nodes that need to be traversed for arriving at a desired node Absolute path: any path specifier starting from the very root node of the tree The root name is, usually, a drive letter (such as C, D etc...) Path specifier example: C:\Windows\System32\calc.exe Relative path: a path starting at some other, already known, node of the tree Example: System32\calc.exe Path separators: collon (:) between the drive letter and the rest of the path Backslah (\) for separating the folder names walked across the path (and between the last folder and a file name)

15 System libraries (Win32) - File management
Relevant functions: CreateFile: create (or open an existing) file GetFileSizeEx: requests the number of bytes occupied by the given file SetFilePointer: (re)position the file position at the specified byte index ReadFile: read data from file to a memory buffer WriteFile: save the content of the memory buffer to the file CopyFile: create a copy of a file MoveFile: move a file to a different folder/location FindFirstFile/FindNextFile/FindClose: iterate all files matched by a (glob) name pattern CreateDirectory: create a new folder RemoveDirectory: delete an existing folder GetCurrentDirectory: retrieve the working directory of the application Working folder: all relative paths are, by default, considered as starting here (at this tree node) Each program has its own working directory, set by the OS when the .exe is loaded SetCurrentDirectory: change the current working directory to point to a different folder Remarks Powerful but complex (many parameters) => it’s important to read their documentation! They’re all exported by kernel32.dll Both ANSI and UNICODE versions are available for all the functions having strings as inputs The C standard library functions are, in the end, wrappers over these functions

16 System libraries - File management examples
Following the steps for calling CreateDirectoryA – 1 – We retrieve the function’s name, if not already known Inspecting the official docs ( for Windows Desktop applications, there’s a Windows API Reference where we can find function names grouped by common functionallity Data access and storage → Local File Systems → Directory Management → Directory Management Reference → Directory Management Functions → CreateDirectory Extracting subroutine information The name, type and parameter meanings (STDCALL implied)

17 System libraries - File management examples
Following the steps for calling CreateDirectoryA – 2 – Info about the type and meaning of the returned value The list of necessary (or related) files for using the function DLL: the dynamic-link library containing the implementation Library: import library (useful/necessary only for COFF builds) Header: C header file describing the involved data types and symbolic constants

18 System libraries - File management examples
Following the steps for calling CreateDirectoryA – 3 – Add the required NASM declarations For OMF, the library name must be specified by using the import directive Declare the function extern as there’s no local implementation provided OMF COFF Important: COFF enforces C++ name mangling! Perform the function call For OMF, the function pointer needs to be dereferenced by the call instruction COFF treats the function name directly as a label See Interfacing with high-level languages for a complete description of the call requirements import CreateDirectoryA kernel32.dll extern CreateDirectoryA extern call [CreateDirectoryA] ; similar to a CreateDirectoryA dd address_of_code call ; just like an asm CreateDirectoryA: ... function

19 System libraries - File management examples
Following the steps for calling CreateDirectoryA – 4 – Assembling the NASM code OMF: nasm.exe -fobj file.asm COFF: nasm.exe -fwin32 file.asm Repeat the command individually for each file if there are more than one files Linking the object file(s) OMF: alink.exe file.obj -oPE -entry start –subsys console (whitespace separated) multiple .obj file names can be sent at once COFF: link.exe file.obj kernel32.lib -entry:start -subsystem:console Kernel32.lib is the import library file from 2.d) As many import libraries as needed can be specified (separated by whitespaces) See Implementing user libraries if building a library instead of an .exe file! Running the program (or, using the library) Run: file.exe Debug: ollydbg.exe file.exe Library: repeat the steps for a new program

20 System libraries – File management examples
OMF: Creating a ”temp” sub-folder in the current working directory ; exemple1.asm import CreateDirectoryA kernel32.dll ; the import directory is OMF-specific! import exit msvcrt.dll extern CreateDirectoryA, exit segment code use32 global start start: push dword nume ; first parameter – the name of the folder push dword 0 ; lpSecurityAttributes is optional, it can be NULL call [CreateDirectoryA] ; an ASCII string is sent => use the ANSI function ; STDCALL => arguments already freed by the callee not eax ; eax is a BOOL value that needs negation for translating push eax ; a TRUE result to a 0 argument for exit (meaning success) call [exit] segment data use32 nume db 'temp', 0 Necessary build commands Assembling: nasm.exe -fobj example1.asm Linking: alink.exe example1.obj -oPE -entry start -subsys console Program execution: example1.exe

21 System libraries – File management examples
COFF: opening a file, reading and displaying its beginning – 1 – ; example2.asm ; we’re using kernel32.lib (an import lib found in both the windows SDK and the MS VC++) ; all kernel32.lib names are decorated for MS VC++ with the STDCALL calling convention extern _printf, _exit ; 28=7*4, 20=5*4, 4=1*4… global start FILE_ATTRIBUTE_NORMAL equ ; These constants are found in the official OPEN_EXISTING equ ; Microsoft documentation of the used functions. GENERIC_READ equ 0x ; The constants and the subroutines are documented INVALID_HANDLE_VALUE equ ; at segment code use32 start: push dword ; hTemplateFile is optional and can be 0 push dword FILE_ATTRIBUTE_NORMAL ; dwFlagsAndAttributes parameter push dword OPEN_EXISTING ; dwCreationDisposition push dword ; lpSecurityAttributes, optional 0 push dword ; dwShareMode, optional 0 push dword GENERIC_READ ; dwDesiredAccess push dword file_name ; lpFileName call ; open the file: HANDLE WINAPI CreateFile(...) cmp eax, INVALID_HANDLE_VALUE ; did it return INVALID_HANDLE_VALUE? jz .error ; if yes, we won’t be able to read anything

22 System libraries – File management examples
COFF: opening a file, reading and displaying its beginning – 2 – mov [file_id], eax ; save it’s id (HANDLE) as eax is a volatile reg. push dword ; lpOverlapped, optional 0 push dword bytes_read ; lpNumberOfBytesRead push dword buffer.size ; nNumberOfBytesToRead push dword buffer.address ; lpBuffer push eax ; hFile call ; read data from file: BOOL WINAPI ReadFile(...) test eax, eax ; is eax = false = 0 ? je .error ; abort if it’s false mov eax, [bytes_read] ; eax = the byte count for the data read mov byte [buffer.address + eax], 0 ; add a NULL termainator at the end of the data push dword buffer.address ; send by reference the data buffer to printf push dword format_string ; %s call _printf ; display the content (it’s NULL-terminated=>safe) add esp, 2* ; cdecl – we (the caller) have to free the stack! push dword [file_id] ; handle = the file’s identifier call ; closing the handle means closing the file sub eax, eax ; prepare eax = exit code (= 0 to signal success) jmp .finish ; jump to the exit point with eax = success

23 System libraries – File management examples
COFF: opening a file, reading and displaying its beginning – 3 – .error: mov eax, ; exit with eax=1 to signal we were unsuccessful .finish: push eax ; exit code parameter value call _exit ; exit the application segment data use32 public data ; link.exe makes the segment read-only if the segment’s ; type (data) is not specified together with its name! file_name db "example2.asm", 0 buffer.size equ 256 buffer.address resb buffer.size bytes_read dd 0 file_id dd 0 format_string db "%s", 0 Necessary commands: Assembling: nasm.exe -fwin32 example2.asm Linking: link.exe example2.obj kernel32.lib msvcrt.lib -entry:start -subsystem:console /NODEFAULTLIB, although still valid, is not needed if at least one Visual C .lib is specified! Running: example2.exe

24 System libraries – Process management
Important functions: CreateProcess: run an application; a running instance of a program is also known as a process WinExec: a similar (but deprecated) function, kept only for compatibility reasons ShellExecute (shell32.dll): performs the same operation a double-click on the file would! ExitProcess: exit the program (like the C exit function, which wraps a call to ExitProcess itself) TerminateProcess: finish the execution of another process GetCommandLine: retrieve the program’s command line Sleep: take a break and let the CPU execute other tasks for a given length of time EnumProcesses: store the identifiers of all currently running processes into an array GetCurrentProcessId: returns a numeric value used as a unique identifier of the program GetProcessWorkingSetSize: returns the amount of memory used by a process QueryProcessCycleTime: retrieve information about a the CPU overhead of a given process Remarks Complex, yet powerful => reading their documentation is a must! Except for ShellExecute, they’re all exported by kernel32.dll They have both ANSI and UNICODE variants: the actual names are CreateProcessA, CreateProcessW...

25 System libraries – Process management example
OMF: printing the program’s command line import printf msvcrt.dll import ExitProcess kernel32.dll import GetCommandLineA kernel32.dll extern printf, ExitProcess, GetCommandLineA global start segment code use32 start: ; GetCommandLine has no parameters call [GetCommandLineA] ; call the ANSI version of LPTSTR WINAPI GetCommandLine(void); push eax ; result = eax = address of the command line string push dword format_string ; %s call [printf] add esp, 2*4 push dword ; exit code argument call [ExitProcess] ; done, exit the program segment data use32 format_string db "%s", 0

26 System libraries – Memory management
Important functions: VirtualAlloc: reserve and/or allocate an address range inside the program’s address space VirtualAllocEx: similar to VirtualAlloc, but supports altering the memory seen by other processes too (→ shared memory) VirtualFree(Ex): Free the memory reservation or allocation at a given address range HeapAlloc, HeapReAlloc, HeapFree: dynamically re/allocate or free memory on a heap IsBadReadPtr, IsBadWritePtr, IsBadCodePtr: probe for read, write or execute access rights HeapCreate, HeapDestroy: create or destroy new heaps! CopyMemory, MoveMemory, FillMemory, ZeroMemory: copying and memory initializations MapViewOfFile: maps the memory seen in an address range directly to the content of a file! Remarks They offer fine-grained control over the access rights and the precise memory layout (what is each address interval mapped to) seen by an application Other third-party libraries or programming languages do not offer this low-level control They’re all part of the kernel32.dll library Using some of these functions requires advanced knowledge regarding the x86 CPU’s protected mode, especially an understanding of the virtual memory concepts, knowledge that is beyond the scope of this course. The official documentation covers the very basic notions that are needed and also provides some example code, just enough for perfoming the calls.

27 System libraries – Memory management example
Counting how many times each BYTE occurs in a file – 1 – import printf msvcrt.dll ; the OMF format is required due to using import! import ExitProcess kernel32.dll import HeapAlloc kernel32.dll import HeapFree kernel32.dll import CreateFileA kernel32.dll import ReadFile kernel32.dll import CloseHandle kernel32.dll import GetProcessHeap kernel32.dll import GetFileSizeEx kernel32.dll extern printf, ExitProcess, HeapAlloc, HeapFree, CreateFileA, ReadFile extern CloseHandle, GetProcessHeap, GetFileSizeEx global start FILE_ATTRIBUTE_NORMAL equ ; Constant definitions from the Microsoft’s OPEN_EXISTING equ ; documentation GENERIC_READ equ 0x ; Check the online documentation at INVALID_HANDLE_VALUE equ ; for addition details FILE_SHARE_READ equ 1 FILE_SHARE_WRITE equ 2 FILE_SHARE_DELETE equ 4 ; build a bit-mask that would allow other processes full access to the file we’re inspecting: FILE_SHARE_ALL equ FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE

28 System libraries – Memory management example
Counting how many times each BYTE occurs in a file – 2 – segment code use32 start: ; opening the file by calling the ASNI version of CreateFile (CreateFileA) push dword ; hTemplateFile push dword FILE_ATTRIBUTE_NORMAL ; dwFlagsAndAttributes push dword OPEN_EXISTING ; dwCreationDisposition push dword ; lpSecurityAttributes push dword FILE_SHARE_ALL ; dwShareMode: allow access, we don’t own it! push dword GENERIC_READ ; dwDesiredAccess push dword file_name ; lpFileName: we’re opening kernel32.dll call [CreateFileA] ; HANDLE WINAPI CreateFile(...) cmp eax, INVALID_HANDLE_VALUE ; is the returned handle = INVALID_HANDLE_VALUE? jz .error ; if true, we won’t be able to do any further operations mov [file_id], eax ; store the value of the volatile register eax push dword file_size ; pass the variable by it’s address (reference) push eax ; the file handle (eax didn’t suffer any changes yet) call [GetFileSizeEx] ; find its size in bytes: BOOL WINAPI GetFileSizeEx(...) test eax, eax ; eax = false = 0? jz .close ; if so, the operation has failed cmp dword [file_size+4], ; check if the high 32 bits part is 0 jnz .close ; if not, abort, the file is too large / unsupported (>4GB)

29 System libraries – Memory management example
Counting how many times each BYTE occurs in a file – 3 – ; no arguments - get the default heap (a handle) for allocating memory call [GetProcessHeap] ; ask for a handle: HANDLE WINAPI GetProcessHeap(..); test eax, eax ; did it return NULL? jz .close ; abort if NULL mov [heap_id], eax ; store the handle for further heap operations push dword [file_size] ; dwBytes: how many bytes to allocate push ; dwFlags: 0, no custom flags/options push dword [heap_id] ; hHeap: the heap's identifier call [HeapAlloc] ; allocate memory: LPVOID WINAPI HeapAlloc(...) test eax, eax ; did we get a NULL pointer as a result? jz .close ; abort if this is the case mov [mem_pointer], eax ; remember the address of the newly allocated memory push dword ; lpOverlapped: optional, we can send a 0 push dword bytes_read ; lpNumberOfBytesRead: by reference (set by the function) push dword [file_size] ; nNumberOfBytesToRead: by value push dword [mem_pointer] ; lpBuffer: bufferul (prin referinta) push dword [file_id] ; hFile: fisierul din care citim call [ReadFile] ; BOOL WINAPI ReadFile(...) test eax, eax ; eax = false = 0 ? je .free ; then free the memory and exit

30 System libraries – Memory management example
Counting how many times each BYTE occurs in a file – 4 – mov ecx, [bytes_read] ; we'll repeat for each byte read jecxz .free ; make sure we don't loop with ecx = 0 mov esi, [mem_pointer] ; mem_pointer is a pointer variable, not just a label! .count_next: lodsb ; load next byte from buffer (DF=0 as we didn't set it) movzx edi, al inc dword [counters + edi*4] ; increment the corresponding DWORD loop .count_next ; and continue for all the remaining bytes sub ebx, ebx ; start at index = 0 (ebx keeps its after external calls) mov esi, counters ; esi points to the very first DWORD (counter[0]) .print_next: lodsd ; load the counter value to eax push eax ; how many times the byte was encountered push ebx ; the value of the byte (0..255) push format_string ; "%d: %d", 10, 13 call [printf] ; printf("%d: %d\n", byte_value, counter[byte_value]) add esp, 3* ; free the 3 parameters from the stack add bl, ; advance (we're avoiding INC as it leaves CF unchanged!) jnc .print_next ; repeat until there CF is set (BL would be above 255) mov dword [cod_iesire], ; assign 0 (the success value) to exit_code ; exit_code is 1 unless we get to this point

31 System libraries – Memory management example
Counting how many times each BYTE occurs in a file – 5 – .free: push dword [mem_pointer] ; pointer to the memory we're freeing push dword ; no special options push dword [heap_id] ; heap identifier call [HeapFree] ; call BOOL WINAPI HeapFree(...) ignoring the result .close: push dword [file_id] call [CloseHandle] ; CloseHandle will close the file .error: push dword [exit_code] ; 0 for success or 1 otherwise call [ExitProcess] segment data use32 public data file_name db 'c:\windows\system32\kernel32.dll', 0 ; read the data from kernel32.dll! file_id dd ; identifier of the file used for reading the bytes heap_id dd ; the identifier for the implicit heap of the process mem_pointer dd ; a pointer to the dynamically allocated heap memory exit_code dd ; 0 = success, 1 = error (preinitialized) file_size dq ; a QWORD, a file size doesn't necessarily fit in 32 bits bytes_read dd ; how much data (bytes) were read counters times 256 dd ; 256 DWORD entries, already 0-initialized format_string db "%d: %d", 10, 13, 0

32 The C standard library Purpose: provide a standard set of abstractions that hide the hardware and operating system complexity. Platform-independent set of functions (there are different implementations available for different platforms) Although the C library by itself is standard and platform-independent, ASM programs using it are not! Operations: Input/output: keyboard, console Process management: run external commands, exit program Memory management: heap re/allocate and free File management: create, read, write and delete files Various common operations: conversions, sorting, pseudo-random numbers, string operations, mathematical functions Easier to use but more limited than the system libraries The CDECL calling convention is used by all functions The msvcrt.dll dynamic library is part of the OS installation files It implements an older version of the standard, used mainly by the OS Many other implementations are available (C Runtime Libraries), including static

33 The C standard library - properties
Numeric types: char/short/int/long/size_t They are signed (except for size_t) BYTE/WORD/DWORD integers Character string: char* in the C language, * marks a pointer to an instance of the preceding type The void type Procedures that return nothing (eax has no assigned meaning after the call) void * is the type of a pointer referencing some raw, untyped memory region All character strings are NULL terminated The errno variable contains a numeric code describing the last error reason (it is one of the library exports!) Rigour and genericity were sacrificed for simplicity The interface is problematic and many times inconsistent Many of the exported functions are deemed unsafe and should be avoided for the better (yet nonstandard) alternatives provided as a substitute by various compilers or operating systems.

34 The C standard library – file management
Also known as streams, they allow sequential input/output access to various devices abstracted as files Main functions: fopen: open a stream for read and/or write operations The data will be either treated as text or binary (a sequence of bytes) fclose: close a file opened with fopen and free any related resources fread: read data from a stream already opened by fopen fwrite: write data to a stream ftell: retrieve the current position inside the stream fseek: set the current stream position feof: check for end-of-file (current stream position being right after the end of data) fprintf: similar to printf but writes the output to a stream fscanf: just like scanf but using a stream as input .... There are many more, with a lot of them being redundant and offered for convenience only Remark: they all call the kernel32.dll system functions internally → they’re inherently slower than the underlying system functions

35 The C standard library – file management example
Counting the words in a text file – 1 – import fopen msvcrt.dll import fscanf msvcrt.dll import fclose msvcrt.dll import printf msvcrt.dll import exit msvcrt.dll extern fopen, fscanf, fclose, printf, exit global start segment code use32 start: push dword access ; "r": read access right push dword file.name ; "exemplu.asm" call [fopen] ; C fopen("example.asm", "r") add esp, 2* ; free the arguments (cdecl…) test eax, eax ; check if the returned pointer to a FILE object is null jz .error ; and exit in that case mov [file.pointer], eax ; store the returned pointer for later use sub esi, esi ; esi = state = 0 outside of a word, 1 inside a word mov edi, esi ; edi = 0 = current word count mov ebx, letters ; lookup-table for word characters vs other characters

36 The C standard library – file management example
Counting the words in a text file – 2 – .repeat: push dword character ; reference to the variable to fill-in push dword character.format ; "%c" push dword [file.pointer] ; the FILE pointer, sent by value call [fscanf] ; C fscanf(file.pointer, "%c", &character) add esp, 3* ; free parameter stack cmp eax, ; did we read precisely one entry? jne .done ; exit the repeat block if not mov al, [character] ; prepare al = the character to check xlat ; verify if it is a word character: al <- [ebx+al] movzx eax, al ; zero-extend to whole eax cmp eax, esi ; check if the character type has changed je .repeat ; if there’s no change then process the next one inc edi ; otherwise increment the number of words mov esi, eax ; and remember the new state / character type jmp .repeat .done: push dword [file.pointer] ; the file pointer call [fclose] ; free any file-associated resources add esp, 1* ; free the parameter from stack

37 The C standard library – file management example
Counting the words in a text file – 3 – push edi ; edi = word counter push dword message.success ; "Total number of words: %d" call [printf] ; C printf("... %d", word_count) add esp, 2* ; free the arguments jmp .finish .error: push dword message.error call [printf] ; C printf("Could not...") add esp, 1*4 .finish: push dword ; always return exit code 0 call [exit] ; as an error message is printed when necessary segment data use32 file.name db "example.asm", ; the name of the input file file.pointer dd ; fopen will save the FILE pointer here access db "r", ; access rights: r=read caracter db ; current character code caracter.format db "%c", ; character (%c) format string message.succes: db “Total number of words: %d", 0 message.error: db "Could not open the file", 0

38 The C standard library – file management example
Counting the words in a text file – 4 – letters: ; lookup table for distinguishing character types times 'A' ($-letters) db 0 ; nothing before the `A` letter (65 ASCII code) times 'Z' ($-letters) db 1 ; everything up to and including `Z` times 'a' ($-letters) db 0 ; nothing until `a` times 'z' ($-letters) db 1 ; all up to `z` times ($-letters) db 0 ; and nothing from z until the end

39 Implementing user libraries
Implementation concerns Supported by many languages, NASM being no exception A quick review of the main library types: Static (.LIB) = the external resources are copied inside the program using them Dynamic (.DLL) = the program contains references only to the needed resources Import libraries, although having the same .LIB extension as the static ones, only offer information about the DLL containing the code / data. There are two ways of writing NASM libraries: The export directive, available only when using the OMF object files Both the -fobj nasm flag and alink.exe for the linking step are needed It offers no support for static library creation! Export via .DEF files (module-definitions file), in conjunction with the COFF format: It entails the -fwin32 assembler flag and the Microsoft’s link.exe linker Static libraries (.LIB) can only be built in this manner! In both cases, the exported symbols must be declared global! All the multi-module programming concepts apply to library writing too! A library can be built by linking together one or more object files, static libraries and can make use of dynamic libraries, all written in potentially different programming languages!

40 Implementing user libraries
Implementation concerns All dynamic libraries have a start subroutine, just like an usual program Responsible for preparing the library for usage (memory allocations, initializations etc...) The start routine must return a logically true value, otherwise it won’t load! Described by the MSDN docs as BOOL WINAPI DllMain(3 arguments) Static libraries don’t use a start routine Static or dynamic library? How to decide? Is the program composed of many executable files or libraries that need the same resources? Does some component need support for individual updates? Then, most likely, such resources are suited to be placed inside a dynamic library. Is it a trivial program? Is a single, stand-alone file program needed? Use static libraries! OMF or COFF? Only NASM code? Don’t bother, the export directive is really handy  → OMF Is it a library combining NASM with other languages? → COFF

41 Implementing user libraries – ASM steps
For a dynamic library a start subroutine is needed, able to receive 3 DWORD arguments and returning a non-zero value The labels preceding the exported resources must be declared global, including the start label (if it is a dynamically-linked library) Only code and variables can be exported, i.e. macro names (%define or %macro) and EQU-defined constant are not supported! The global directive, although necessary, is not enough for the export! It’s effect is only to allow access (for the linker) to the said resource without actually exporting it Designate the names as public exports of the resulting library For OMF this is easily done through the export directive, used as follows: In case the COFF format is used, a new Module-Definitions File (.DEF) is needed. This file should specify a name for the library (with internal use only) and each resource contained/exported by the new library: global function1, var2 ; one or more comma-separated identifiers export function1 PublicName ; resources can be published under different names! export var ; or, this way, exports can leave the name unchanged LIBRARY internal_name ; ASM style comments are permitted EXPORTS function ; only a single name is allowed on each line! var ; and so on, one line for each exported name

42 Implementing user libraries – ASM steps
The .def file fills-in the same role played by the export directive for OMF These files can additionally contain other definition types (regarding the structure of the program / library), useful in other scenarios, besides writing ASM libraries, and their use is documented by Microsoft on their website The module-definitions files are useful for various C/C++ programs too! Assembling the NASM code OMF: nasm.exe -fobj file.asm → file.obj COFF: nasm.exe -fwin32 file.asm → file.obj If needed, the command should be repeated in a similar manner for any additional files Linking the resulting library OMF: alink.exe file.obj -oPE -dll -entry start → file.dll COFF, static library: link.exe /lib file.obj /NODEFAULTLIB → file.lib COFF, dynamic library: link.exe /dll file.obj /entry:start /def:file.def → file.dll COFF, (opțional) import lib: lib.exe /def:file.def /machine:x86 → file.lib An arbitrary number of object files (and static libraries for COFF) can be linked together if their names are listed comma-separated in any of the above linker command-lines

43 Implementing user libraries – Example
Exporting two functions from a dynamic library – 1 – DoubleDivision, performing a QWORD to DWORD unsigned integer division DoubleMultiplication which will multiply two DWORD unsigned integers resulting a QWORD value OMF format is assumed Step 1: First things first, a start routine is needed The three input arguments of the start subroutine are: hInstDll: a HANDLE value used by the library to identify itself for internal management (it might call FreeLibrary to unload itself, for example) fdwReason: start is called for signaling various events (library load/unload, new thread created etc…) by specifying a reason code lpvReserved: unused and undefined In our trivial example the three parameters are not used, their existence is only important at the cleanup stage where the stack storage need to be freed, due to using the STDCALL convention Step 2: start, DoubleDivision and DoubleMultiplication need to be flagged as global Step 3: by using the export directive the two functions are easily marked as library exports export DoubleDivision export DoubleMultiplication global start, DoubleDivision, DoubleMultiplication segment code use32 code start: ; being named “start” is not a must, it only has to fit the ; BOOL WINAPI DllMain(hInstDll, fdwReason, lpvReserved) signature mov eax, ; return eax = 1 = TRUE to avoid the operation being treated as failed ret 3* ; free the 3 arguments and return the true value found in eax

44 Implementing user libraries – Example
Exporting two functions from a dynamic library – 2 – ; int WINAPI DoubleDivision(int NumeratorSup, int NumeratorInf, int Denominator) DoubleDivision: .NumeratorHigh equ 4 + 1* ; EBP-relative offset of high numerator part .NumeratorLow equ 4 + 2* ; the second argument (low part of the numerator) .Denominator equ 4 + 3* ; third parameter push ebp ; prepare a stack frame for the function mov ebp, esp cmp dword [ebp + .Denominator], 0 ; is the denominator zero? jz .avoid_division ; if yes, skip (division by zero isn’t possible) mov edx, [ebp + .NumeratorHigh] ; EDX = high part mov eax, [ebp + .NumeratorLow] ; EAX = the low DWORD part div dword [ebp + .Denominator] ; EAX<-EDX:EAX/Denominator (EDX<-remainder, ignored) .avoid_division: pop ebp ret 3* ; nothing to restore, only volatile registers were used

45 Implementing user libraries – Example
Exporting two functions from a dynamic library – 3 – ; int WINAPI DoubleMultiplication(int Factor1, int Factor2, int *ResultHigh) DoubleMultiplication: .Factor equ 4 + 1*4 ; first argument .Factor equ 4 + 2*4 ; note the use of the local-label mechanism for EQU constant! .ResultHigh equ 4 + 3*4 ; the actual (full) name is DoubleMultiplication.ResultHigh push ebp ; prepare a stack frame mov ebp, esp mov eax, [ebp + .Factor1] ; EAX = first factor mov edx, [ebp + .Factor2] ; EDX = second factor mul edx ; EDX:EAX = the 64 bit product result cmp dword [ebp + .ResultHigh], 0; is the pointer NULL (=0)? jz .done ; if indeed NULL, avoid dereferencing it mov ecx, [ebp + .ResultHigh] ; ECX = pointer value (the address referenced by the pointer) mov [ecx], edx ; save the high part of the result to the specified address .done: pop ebp ; no other registers need to be restored ret 3* ; return and free the 4 stack locations used by the arguments

46 Implementing user libraries – Example
Exporting two functions from a dynamic library – 4 – Assuming the NASM file is saved as ”library.asm”, the necessary steps for building the library are: Step 4: assemble the asm source code: nasm -fobj library.asm Step 5: link the object file: alink.exe library.obj -oPE -dll -entry start The resulting dynamic library (library.dll) can be used as part of any program, no matter the programming language as long as that specific language (its Foreign-Function Interface) offers support for using dynamic libraries and can handle the call convention (STDCALL in this example)

47 Implementing user libraries – Example
Exporting two functions from a dynamic library – 5 – Let’s also exemplify how the library might prove useful to a new ASM program: the following code will divide 0x to 1*GIGA and then it will call printf to display the value (0x48D159E) import DoubleDivision library.dll import printf msvcrt.dll import ExitProcess kernel32.dll extern DoubleDivision, printf, ExitProcess global start segment code use32 code start: push dword 1024*1024* ; denominator: (((1024=KILO)*1024)=MEGA)*1024)=GIGA push dword 0x ; NumeratorLow: low DWORD part of (0x ) push dword 0x ; NumeratorHigh: high part of (0x ) call [DoubleDivision] ; perform the division operation (0x / GIGA) push eax ; the value to print push dword fmt ; printf("0x / GIGA = 0x%X", eax) call [printf] ; call printf add esp, 2* ; free the printf arguments (printf uses cdecl) push dword ; 0 is considered a success code for ExitProcess call [ExitProcess] ; done, finish execution fmt: db "0x / GIGA = 0x%X", 0 ; %X will print a hexadecimal number

48 Implementing user libraries – Example
Exporting two functions from a dynamic library – 6– Let’s take a look at what the COFF version of the example would look like: The export directive cannot be used and Step 3 asks for a .def file instead: ; the library.def file LIBRARY library EXPORTS DoubleDivision DoubleMultiplication The only code change (due to the third step still) is the elimination of all export declarations: global start, DoubleDivision, DoubleMultiplication segment code use32 code start: ; being named “start” is not a must, it only has to fit the ; BOOL WINAPI DllMain(hInstDll, fdwReason, lpvReserved) signature The 4 and 5 steps would consist of issuing the following commands: Step 4 – assemble the file: nasm -fwin32 library.asm Step 5.c) – link editing: link.exe /dll library.obj /entry:start /def:library.def Step 5.d) – creating an import library, optional: lib.exe /def:library.def /machine:x86

49


Download ppt "Multi-modules programming"

Similar presentations


Ads by Google