NASM Forum > Example Code

BASELIB: General Purpose Lib for Beginners

(1/10) > >>

stressful:
I make a new thread because the old one is too messy and misleading

Attached is 6 source files and 6 binaries that can be used to facilitate learning of NASM, intended for beginners.

Source format (You can start practicing straight out of the box)

--- Code: ---1. base32x.asm - Source for Linux32.
2. base32w.asm - Source for Win32
3. base64w.asm - Source for Win64.
4. base64x.asm - Source for Linux64.
5. sbase32x.asm - Source for Linux32 (stack version)
6. sbase32w.asm - Source for Win32 (stack version)
--- End code ---

Binaries format

--- Code: ---1. base3.o - the 32-bit library for Linux. Static library
2. base6.o - the 64-bit library for Linux. Static library.
3. base3.dll - same as 1) but for Windows. Dynamic
4. base6.dll - same as 2) but for Windows. Dynamic
5. sbase3.o - 32-bit lib, stack version for Linux. Static
6. sbase3.dll - 32-bit lib, stack version for Windows. Dynamic
--- End code ---

Each folder has their own readme.txt and sample files demonstrating how to use the binaries properly. These libs are extremely low level and designed from instruction sets point of view. Not many high-level constructs and no C library is harmed while making these libs. Just plain instructions and minumum syscalls. CAUTION: This lib is not optimized and not intended for purposes other than as learning/helper tools.     

Hope u like it. Cheers and happy learning.

If u found any bugs or have any suggestions, do contact me. e-mail is in the Docs.

Revision  Nov 7th, 2016)

--- Code: ---.small fixes to "fpu_round" and "sse_round" (stack versions only).

--- End code ---


LIST OF BASELIB ROUTINES

--- Code: ---Notes   : The number in braces shows the # of arguments required       
        : /Followed by the return value(s) (if applicable)       
        : The list is for 64-bit versions only 
------------------------------------------------------------------
Routines(177+2)        Descriptions
------------------------------------------------------------------
prnreg(1)       - Display register (hex)
prnregd(1)      - Display register (decimal)     
prnregdu(1)     - Display register (unsigned decimal)     
dumpreg(1)      - Display register dump (hex)
dumpseg         - Display segment registers dump (hex)
stackview(1)    - Display stack
memview(2)      - Display memory dump   
memviewc(2)     - Display memory dump, emphasis on string 
mem_reset(2)    - Reset memory content 
mem_set(3)      - Fill up memory content   
mem_insertr(2)  - Insert register content into memory
mem_copy(3)     - Copy memory block
mem_load(1)/2   - Load a file to memory 
opcode(2)       - Display encoding between 2 labels 
opsize(2)/1     - Get code size between 2 labels. 
flags(1)        - Display RFLAG     
prnint(1)       - Display signed integer     
prnintu(1)      - Display unsigned integer     
prnhex(1)       - Display hexadecimal     
prnhexu(1)      - Display unsigned hexadecimal     
prnoct(2)       - Display octal     
prnoctu(2)      - Display unsigned octal     
prnbin(1)       - Display signed binary     
prnbinu(1)      - Display unsigned binary     
prnbinf(3)      - Display formatted binary     
prnbinb(1)      - Display binary with byte separators     
fpbin(1)        - Display 64-bit Floating Point binary     
fpbind(1)       - Display 32-bit Floating Point binary     
prndbl(1)       - Display 64-bit precision value
prndblr(1)      - Display 64-bit precision value (rounded)   
prndble(2)      - Display 64-bit precision with decimal places     
prndblx(1)      - Display 80-bit precision value     
prnflt(1)       - Display 32-bit float value
prnfltr(1)      - Display 32-bit float value (rounded)   
dblsplit(1)/2   - Split a real8 into parts 
fpdinfo(1)      - Display Double binary information     
fpfinfo(1)      - Display Float binary information     
dec2str(2)      - Convert signed decimal to 0-ended string       
dec2stru(2)     - Convert unsigned decimal to 0-ended string       
hex2str(2)      - Convert signed hex to 0-ended string
hex2stru(2)     - Convert signed hex to 0-ended string
bin2str(2)      - Convert signed binary to 0-ended string
bin2stru(2)     - Convert unsigned binary to 0-ended string
flt2str(2)      - Convert a float to 0-ended string
dbl2str(3)      - Convert double to 0-ended string
readint/1       - Get an integer from kboard
readdbl/1       - Get a double from kboard 
readflt/1       - Get a float from kboard 
fpu_stack       - Display FPU stack     
fpu_sflag       - Display FPU Status flag   
fpu_cflag       - Display FPU Control flag     
fpu_tag         - Display FPU Tag Word status     
fpu_reg(1)      - Display one FPU register     
fpu_copy(1)/1   - Copy a FPU register 
fpu_precision(1)- Set FPU precision   
fpu_round(1)    - Set FPU rounding control   
sse_round(1)    - Set SSE rounding control   
sse_flags       - Display SSE flags     
prnmmx(2)       - Display one MMX register       
dumpmmx(1)      - Display MMX dump       
prnxmm(2)       - Display one XMM register       
dumpxmm(1)      - Display XMM dump       
clearxmm        - Clear all xmm registers     
prnymm(2)       - Display one YMM register       
dumpymm(1)      - Display YMM dump       
clearymm        - Clear all ymm registers     
prnintd(2)      - Display 32-bit integer     
prnintw(2)      - Display 16-bit integer     
prnintb(2)      - Display byte integer     
str2int(1)/1    - Convert 0-ended string to integer 
str2dbl(1)/1    - Convert 0-ended string to double 
str2flt(1)/1    - Contert 0-ended string to float 
dbl2int(1)/1    - Convert double to integer 
int2dbl(1)/1    - Convert integer to double 
isint(1)/1      - Check if an FP is a qualified integer 
rndint(1)       - Generate 1 random integer
rand(1)/1       - Get one unsigned random int
randq(2)/1      - Generate unique random ints & save
factorial(1)/1  - Get factorial
powint(2)/1     - Calculate x ^ n (Integer) 
pow2(1)/1       - Calculate 2 ^ n (Integer) 
iseven(1)/1     - Check if a number is even 
isodd(1)/1      - Check if a number is odd 
bconv(2)        - Convert & display from normal bases to other bases     
bitfield(3)     - Extract bitfield of a given data
addf(2)/1       - Floating Point ADD     
subf(2)/1       - Floating Point SUB     
mulf(2)/1       - Floating Point MUL     
divf(2)/1       - Floating Point DIV     
sqroot(1)/1     - Get square root 
fcalc(3)/1      - Two-operands floating point calculator
rad2deg(1)/1    - Convert radian to degree
deg2rad(1)/1    - Convert degree to radian
sine(1)/1       - Get sine of a radian 
tangent(1)/1    - Get tangent of a radian 
cosine(1)/1     - Get cosine of a radian 
sincos(1)/2     - Get Sine and Cosine
atangent(1)/1   - Get arc-tangent of a radian. 
log10(1)/1      - Get a common log for a FP value
ln10(1)/1       - Get a natural log for a FP value     
pow(2)/1        - Calculate x ^ n (precision) 
chr_isdigit(1)/1- Check if a char byte is a digit
chr_isalpha(1)/1- Check if a char is an alphabet 
chr_islower(1)/1- Check if a char is a lower case 
chr_isupper(1)/1- Check if a char is an upper case
chr_change(3)   - Change a char from a 0-ended string
chr_chcase(1)/1 - Change a char's case 
chr_toupper(1)/1- Convert a char to uppercase 
chr_tolower(1)/1- Convert a char to lowercase 
chr_find(2)/1   - Find a char from a 0-ended string 
chr_count(2)/1  - Count a char from a 0-ended string 
ascii(1)        - Simple ascii byte conversion
chr_shuffle(1)  - Shuffle a 0-ended string
str_copy(3)     - Copy a string to another string     
str_length(1)/1 - Find string length.     
str_cmpz(2)/1   - Compare 2 0-ended strings 
str_cmps(3)/1   - Compare 2 strings, with size 
str_toupper(1)  - Up the case of a 0-ended string 
str_tolower(1)  - Lower the case of a 0-ended string 
str_reverse(1)  - Reverse a 0-ended string 
str_trim(2)     - Trim a 0-ended string     
str_wordcnt(1)/1- Word count of a 0-ended string     
str_token(2)    - Display tokens off a 0-ended string     
str_find(3)/1   - Find a sub-string from a 0-ended string 
str_findz(2)/1  - Find a sub-string from a 0-ended string 
str_append(5)/1 - Appends two 0-ended strings, with size 
str_appendz(4)/1- Appends two 0-ended strings 
sort_int(2)     - Sort integer 
sort_byte(3)    - Sort char/byte array 
sort_dbl(3)     - Sort double   
sort_dblx(3)    - Sort real10   
sort_flt(3)     - Sort integer   
digitprob(2)/1  - Extract digit from a signed integer
digitprobu(2)/1 - Extract digit from an unsigned integer
digithprob(2)/1 - Extract digit from a signed hex
digithprobu(2)/1- Extract digit from an unsigned hex
digitscan(2)/1  - Extract digit from a signed integer
digitscanu(2)/1 - Extract digit from an unsigned integer
digithscan(2)/1 - Extract digit from a signed hex
digithscanu(2)/1- Extract digit from an unsigned hex
digitcount(1)/1  - Extract digit from a signed integer
digitcountu(1)/1 - Extract digit from an usigned integer
digithcount(1)/1 - Extract digit from a signed hex
digithcountu(1)/1- Extract digit from an umsigned hex
aprnint(3)       - Display array of signed integers
aprnintu(3)      - Display array of unsigned integers
aprndbl(3)       - Disp array of doubles
aprnflt(3)       - Dspl array of floats
aprndblx(3)      - Display array of real10
halt            - Pause screen
prnspace        - Print a whitespace
prnline         - Print a new line
prnspaces(1)    - Print multiple whitespaces
prnlines(1)     - Print multipls lines
prnchrp(2)      - Display char pattern
prnchrs(1)      - Display a character from the stack
prnchar(1)      - Display a character variable     
prnstrd(2)      - Display delimiter-ended string
prnstreg(1)     - Display short string off RAX
readchr(1)      - Get a character and save to variable
;-----   OS SPECIFICS   -----
prnchr(1)       - Display char in AL
prnstr(2)       - Display string with size
prnstrz(1)      - Display 0-ended string     
readch/1        - Get a char from kboard. Return in AL
readstr(1)/1    - Get a string with size
mem_alloc(1)/1  - Get memory
mem_free(1)/1   - Release memory 
timer_start     - Start a timer (win64 only)     
timer_stop/1    - Stop a timer (win64 only)
delay(1)        - Delay execution in milliseconds
file_new(1)     - Create a new file
file_open(2)    - Open a file with options for read or write 
file_read(3)/1  - Read from an opened file 
file_write(3)/1 - Write to an opened file 
file_close(1)   - Close file handle 
file_size(1)/1  - Get file size 
file_copy(2)    - Copy a file to a new file
exitp           - Pause before exit to system
exitx           - Exit to system
--- End code ---

stressful:
If you don't know how to start, take any example files and start with simple things and short codes. Or you can use the source. This one below is for Linux64 using "base64x.asm" source file;


--- Code: ---;nasm -f elf64 base64x.asm
;ld base64x.o -o base64x
;./base64x

global _start

section .text
_start:
        mov rax,34h           ;your very first instruction ;D
        push 0                ;option to view the register dump as unsigned hex
        call dumpreg          ;See if you managed to put 34h to RAX register. If you did, congratulations!

        call exitx
--- End code ---

The output should be:


--- Code: ---RAX|0000000000000034 RBX|0000000000000000 RCX|0000000000000000
RDX|0000000000000000 RSI|0000000000000000 RDI|0000000000000000
RBP|0000000000000000 RSP|00007FFE5F85AB30 R8 |0000000000000000
R9 |0000000000000000 R10|0000000000000000 R11|0000000000000000
R12|0000000000000000 R13|0000000000000000 R14|0000000000000000
R15|0000000000000000 RIP|0000000000400085
--- End code ---

Helper routines such as dumpreg, stackview, dumpxmm etc are very useful for you to build awareness around your code behaviour at all time until you are satisfied. Don't let the routine codes of dumpreg scare you. Just use the routine. You are probably not ready for the source code just yet. Just worry about your own code.

Practice makes perfect.

stressful:
Another example of basic I/O program in Linux64. This example demonstrates extensive use of basic I/O routines offered by the library;


--- Code: ---; Compile: nasm -f elf64 base64x.asm
; Link : ld base64x.o -o base64x
; Execute: ./base64x

global _start

section .bss
theName resb 100      ;allocation for large buffer
gend resb 1

section .data
hello db "Please input your name: ",0
ageStr db "How old are you?: "
hiMr db "Hi Mr ",0
hiMs db "Hi Ms ",0
gender db "Enter gender [m/f]: ",0
age dq 0

section .text
_start:
mov rax,gender ;ask for gender
call prnstrz
call readch ;get the char
call halt ;hold the screen
mov [gend],al ;copy pressed key into a byte var

mov rax,hello ;ask for name
call prnstrz
mov rax,theName ;read the string to buffer
call readstr ;return 0-ended string buffer

mov rbx,18 ;size of string
mov rax,ageStr ;the string to print. Ask for age
call prnstr ;note, this is prnstr, not prnstrz
call readint ;read integer from keyboard. Return in RAX
mov qword[age],rax  ;save the result to a variable

mov rax,hiMs ;Decision for salutation. Default case
cmp byte[gend],'f'
je .female        
mov rax,hiMr ;Else

.female:
call prnstrz
mov rax,theName
call prnstrz
mov rax,',you`re '
call prnstreg
mov rax,qword[age]
add rax,1
call prnintu
mov rax,' next ye'
call prnstreg
mov rax,'ar'
call prnstreg

call exitx
--- End code ---

Hopefully, with this possible output;


--- Code: ---Enter gender [m/f]: m
Please input your name: Frank Kotler
How old are you?: 34
Hi Mr Frank Kotler,you`re 35 next year
--- End code ---

This example maybe too much for a beginner, but this should give you the basic idea of many things of assembly language, this library and NASM (variables, sections, registers, call instructions, basic anatomy etc).

stressful:
I am trying to give as many examples as possible before I leave  ;D

This example shows how you can save lots of time in trying to grab the idea of an x86 stack (TOS, grows downwards, shrink upwards, push pop etc etc).


--- Code: ---The stack (assumed) empty...
00007FFC2F5AB3AC |00007FFC2F5A9418
00007FFC2F5AB3A1 |00007FFC2F5A9410
00007FFC2F5AB38C |00007FFC2F5A9408
0000000000000000 |00007FFC2F5A9400
00007FFC2F5AB384 |00007FFC2F5A93F8
0000000000000001 |00007FFC2F5A93F0*  ;Top of Stack (TOS)

Stack after two PUSHes...
00007FFC2F5AB38C |00007FFC2F5A9408
0000000000000000 |00007FFC2F5A9400
00007FFC2F5AB384 |00007FFC2F5A93F8
0000000000000001 |00007FFC2F5A93F0 ;Previous TOS
0000000000000045 |00007FFC2F5A93E8 ;Watch the stack 'grows' downwards towards lesser memory
0000000000000077 |00007FFC2F5A93E0* ;New TOS. The last item PUSHed

Stack after one POP...
00007FFC2F5AB3A1 |00007FFC2F5A9410
00007FFC2F5AB38C |00007FFC2F5A9408
0000000000000000 |00007FFC2F5A9400
00007FFC2F5AB384 |00007FFC2F5A93F8
0000000000000001 |00007FFC2F5A93F0
0000000000000045 |00007FFC2F5A93E8* ;New TOS after one item is POPped to RCX
;77h is no longer 'available' on the stack, but RCX now has it
;Stack 'shrinks' upwards the address, one 'notch'
--- End code ---


This effect can be achieved by using "stackview" routine.


--- Code: ---global _start

section .data
empty db 'The stack (assumed) empty...',0ah,0
two db 'Stack after two PUSHes...',0ah,0
one db 'Stack after one POP...',0ah,0
val1 dq 45h    ;will push these two data onto the stack
val2 dq 77h    ;and pop this one later

section .text
_start:
mov rax,empty
call prnstrz
mov rax,6 ;view 6 items of stack
call stackview
call prnline

push qword[val1] ;push a var
mov rax,[val2] ;just a variety. Push a reg
push rax

mov rax,two
call prnstrz
mov rax,6
call stackview
call prnline

pop rcx ;pop 1 item from TOS(*)

mov rax,one
call prnstrz
mov rax,6
call stackview

call exitx
--- End code ---

But you probably don't understand a complicated example like the above. How about exploring it on your own, like this;


--- Code: ---push 45h
push 77h
mov rax,5   ;see 5 items of stack (1 item = 8 bytes)
call stackview
--- End code ---

and see what's the output. Then try popping one item and the print the stackview again. That easy ;D

stressful:
Or maybe you want to try exploring the FPU instruction set on your own...


--- Code: ---global _start

section .data
pointX dq 5.61
pointY dq 3.45

section .text
_start:

finit ;clear FPU, just to be safe.
fld qword[pointX] ;load to ST1
fld qword[pointY] ;load to ST0
call fpu_stack ;See current stack
call prnline
fdiv st0,st1 ;divide st0 by st1, and save the result to ST0
call fpu_stack ;see the result in ST0

call exitx
--- End code ---

And here's the quick and visual output for your next phase of learning ;D


--- Code: ---ST0: 3.450000000000000177
ST1: 5.610000000000000319
ST2: ...
ST3: ...
ST4: ...
ST5: ...
ST6: ...
ST7: ...

ST0: 0.614973262032085558
ST1: 5.610000000000000319
ST2: ...
ST3: ...
ST4: ...
ST5: ...
ST6: ...
ST7: ...
--- End code ---

Note the output is in full REAL10 format while your data is in REAL8 format, so you'll see trailing values from the FPU stack. It's expected and not an error.

Navigation

[0] Message Index

[#] Next page

Go to full version