Author Topic: BASELIB: General Purpose Lib for Beginners  (Read 72690 times)

Offline stressful

  • Full Member
  • **
  • Posts: 105
  • Country: 00
    • CPU2.0
BASELIB: General Purpose Lib for Beginners
« on: September 14, 2016, 02:34:22 PM »
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: [Select]
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)

Binaries format
Code: [Select]
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

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: [Select]
.small fixes to "fpu_round" and "sse_round" (stack versions only).


LIST OF BASELIB ROUTINES
Code: [Select]
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
« Last Edit: November 07, 2016, 01:22:23 AM by stressful »

Offline stressful

  • Full Member
  • **
  • Posts: 105
  • Country: 00
    • CPU2.0
Re: General Purpose Lib for Extreme Beginners
« Reply #1 on: September 14, 2016, 02:56:54 PM »
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: [Select]
;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

The output should be:

Code: [Select]
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

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.
« Last Edit: November 09, 2016, 05:46:06 AM by stressful »

Offline stressful

  • Full Member
  • **
  • Posts: 105
  • Country: 00
    • CPU2.0
Re: General Purpose Lib for Extreme Beginners
« Reply #2 on: September 14, 2016, 03:36:12 PM »
Another example of basic I/O program in Linux64. This example demonstrates extensive use of basic I/O routines offered by the library;

Code: [Select]
; 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

Hopefully, with this possible output;

Code: [Select]
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

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).
« Last Edit: November 09, 2016, 05:41:34 AM by stressful »

Offline stressful

  • Full Member
  • **
  • Posts: 105
  • Country: 00
    • CPU2.0
Re: General Purpose Lib for Extreme Beginners
« Reply #3 on: September 14, 2016, 03:58:58 PM »
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: [Select]
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'


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

Code: [Select]
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

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

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

and see what's the output. Then try popping one item and the print the stackview again. That easy ;D
« Last Edit: October 24, 2016, 11:47:54 PM by stressful »

Offline stressful

  • Full Member
  • **
  • Posts: 105
  • Country: 00
    • CPU2.0
Re: General Purpose Lib for Extreme Beginners
« Reply #4 on: September 14, 2016, 04:19:05 PM »
Or maybe you want to try exploring the FPU instruction set on your own...

Code: [Select]
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

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

Code: [Select]
ST0: 3.450000000000000177
ST1: 5.610000000000000319
ST2: ...
ST3: ...
ST4: ...
ST5: ...
ST6: ...
ST7: ...

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

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.
« Last Edit: October 18, 2016, 08:32:36 PM by stressful »

Offline stressful

  • Full Member
  • **
  • Posts: 105
  • Country: 00
    • CPU2.0
Re: General Purpose Lib for Extreme Beginners
« Reply #5 on: September 14, 2016, 04:22:08 PM »
Good luck and be register-safe!  ;D

Offline stressful

  • Full Member
  • **
  • Posts: 105
  • Country: 00
    • CPU2.0
Re: General Purpose Lib for Extreme Beginners
« Reply #6 on: September 14, 2016, 09:26:12 PM »
Before I forgot, here's one very basic way to use "base6.dll" for windows

Code: [Select]
;Example of accessing "base6.dll" from thisfile.asm
;Compile: nasm -f win64 thisfile.asm
;Link   : golink /console /entry _start thisfile.obj base6.dll
;----------------------
global _start

extern _dumpreg
extern _prnstrz
extern _exitx

section .data
s db 'Hello World',0ah,0

section .text
_start:
        mov     rax,s
        call    _prnstrz
        push    0
        call    _dumpreg
        call    _exitx

Not much different from accessing other DLL files. You need a linker like GoLink btw.
« Last Edit: October 18, 2016, 08:32:54 PM by stressful »

Offline stressful

  • Full Member
  • **
  • Posts: 105
  • Country: 00
    • CPU2.0
Re: General Purpose Lib for Extreme Beginners
« Reply #7 on: September 17, 2016, 06:53:37 PM »
Added and update a few routines.

Revision 2.7 (Sept 18th, 2016)
Code: [Select]
[+] rand - get one unsigned random int of range 0 to N
[+] randq- Generate unique random integers (unsigned) of range 0 to N-1
           and save to an array
[-] rndigit - deleted
[+] int2str
[+] file_copy

Offline stressful

  • Full Member
  • **
  • Posts: 105
  • Country: 00
    • CPU2.0
Re: General Purpose Lib for Extreme Beginners
« Reply #8 on: September 25, 2016, 09:38:41 PM »
I understand that it is a great pain to explain to beginners on basic things like converting an integer to string and anything similar. Without any helper tool (debugger is too much for a 'helper' at beginners level), explanations of things like registers, instructions and their effects can be very time-consuming. One such example is converting 1234 to string "1234" by using repetitive divisions of 10 by using DIV instruction and setup

Example of extracting every digit out of 1234 and convert each digit to their corresponding ASCII characters;
1234/10     = 123, modulo or digit 4  ==> add 0x30, we get char '4' or ASCII 0x34
123/10       = 12, modulo or digit 3  ==> add 0x30, we get char '3' or ASCII 0x33
12/10        = 1, modulo or digit 2 ==> add 0x30, we get char '2' or ASCII 0x32
1/10          = 0, modulo or digit 1 ==> add 0x30, we get char '1' or ASCII 0x31

Which can be done this way for one round digit pass, getting digits from the back
Code: [Select]
;'Confident' mode
xor edx,edx     ;cleared before DIV
mov eax,1234    ;the digit to convert
mov ecx,10
div ecx     ;answer in EAX, modulo in EDX (e,g 1234/10 ==> EAX = 123, EDX = 4)
add dl,0x30 ;convert digit in EDX to ASCII '4'

That's the easy part. The difficult part is the Explanation, and for some beginners, the really need some visual cues to answer their famous 'what-the-hell-is-the instructor-is-talking-about' question. Luckily that can be partially solved by using the routines like "dumpreg", "halt" and "prnchr" where codes like the above can be visually and interactively turned from 'eeww' format into an instructional material to create a more dynamic and interactive teaching and learning setting where helper routines can be inserted at any point of execution. This can greatly saves time and enhance effectiveness.

Code: [Select]
        ;'Instructional' mode
        mov     eax,1234;Value to convert
        mov     ecx,10  ;Divisor
        mov     edx,0   ;Clear before every DIV

        push    1       ;View all involved registers as unsigned int
        call    dumpreg ;watch ECX,EDX and EAX in initial state
        call    halt    ;Pause to observe

        div     ecx     ;Perform DIV. EAX=answer EDX=modulo (remainder)

        push    1       ;view dump as unsigned int
        call    dumpreg ;See changes in EDX and EAX. EDX = 4
        call    halt    ;pause to observe

        add     dl,30h  ;convert digit 4 to ASCII character '4'
        push    0       ;Now view in HEX format
        call    dumpreg ;EDX now becomes ASCII '4'(0x34) no more digit 4
        call    halt

Producing this progressive and interactive output, by using the  "halt" and "dumpreg" combo to explain the code behavior at almost every point of instructions.

First dumpreg output:
Code: [Select]
EAX|0000001234 EBX|0002781184 ECX|0000000010
EDX|0000000000 ESI|0004198400 EDI|0004198400
EBP|0000917396 ESP|0000917380 EIP|0004198415

Second dumpreg output:
Code: [Select]
EAX|0000000123 EBX|0002781184 ECX|0000000010
EDX|0000000004 ESI|0004198400 EDI|0004198400
EBP|0000917396 ESP|0000917380 EIP|0004198429

Last dumpreg output
Code: [Select]
EAX|0000007B EBX|002A7000 ECX|0000000A
EDX|00000034 ESI|00401000 EDI|00401000
EBP|000DFF94 ESP|000DFF84 EIP|0040102C

After a user is satisfied that instructions are all in order and behave as they are intended, the routines can be deleted and the beginners can put their code back to 'confident' mode. LOL ;D
 
« Last Edit: September 26, 2016, 12:33:50 AM by stressful »

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: General Purpose Lib for Extreme Beginners
« Reply #9 on: September 25, 2016, 10:04:27 PM »
Great explaination, stressful! The only thing I would stress is the necessity of zeroing edx before the "div" every time!

Best,
Frank


Offline stressful

  • Full Member
  • **
  • Posts: 105
  • Country: 00
    • CPU2.0
Re: General Purpose Lib for Extreme Beginners
« Reply #10 on: September 25, 2016, 11:31:13 PM »
Yeah I know that Frank but thanks for the reminder. Just wanted to avoid the most common beginners mistakes in such a short explanation. Stay cool Frank. You're my favorite teacher!   

Offline stressful

  • Full Member
  • **
  • Posts: 105
  • Country: 00
    • CPU2.0
Re: General Purpose Lib for Extreme Beginners
« Reply #11 on: September 26, 2016, 12:01:15 AM »
If we ignore the string buffer, we can build a simpler loop from the program above and see all the extracted digits via "dumpreg"

Code: [Select]
            mov eax,1234
            mov ecx,10
.getDigit:
            mov edx,0   ;must be cleared
            div ecx       ;Answer in EAX. Digit in EDX
            add dl,0x30   ;the ASCII char we need. Converted from digit to ASCII.
            push 1          ;push 0 to view in Hex
            call dumpreg
            call halt
            test eax,eax   ;as long as EAX not 0, get next digit
            jnz .getDigit

or perhaps you're done with the dumpreg and wanted to see some real screen output... well why not? If C can do that, ASM can too! But until we get to the buffer/stack processing, we should settle on printing it in reverse order! C can't do this that easy! Hehehe  ;D

Code: [Select]
    global _start

section .text
_start:
    mov eax,1234
    mov ecx,10
.getDigit:
    xor edx,edx
    div ecx
    add dl,0x30
    xchg edx,eax   ;copy edx to eax for prnchr routine
    call prnchr      ;proof that DL is an ascii char. Print the ASCII char in EAX.
    xchg edx,eax   ;restore their previous values
    test eax,eax    ;if EAX <> 0, loop some more. EAX = loop sentinel
    jnz .getDigit
                         ;We reach here if EAX is indeed 0
    call exitx         ;exit the program

But seriously, string processing is not yet necessary because we just want to have a proof-of-concept program - 1) how to split an integer into digits and 2) turn each digit to their ASCII equivalences. That's all that matters right now. There's still more to go (signed and unsigned, overflow, hex, octal etc) but that should do it for now.
« Last Edit: October 18, 2016, 08:34:44 PM by stressful »

Offline stressful

  • Full Member
  • **
  • Posts: 105
  • Country: 00
    • CPU2.0
Re: General Purpose Lib for Extreme Beginners
« Reply #12 on: September 26, 2016, 12:57:42 AM »
Btw, I can't put enough emphasis on the importance of "dumpreg" routine. You need to get yourself familiar with it, and how to properly call it because it's going to be your best buddy. Here's an example of calling the "dumpreg" in 3 different format, displaying the same values;

Code: [Select]
mov eax,-3 ;test value

push 0 ;Display as unsigned Hex
call dumpreg
call prnline

push 1 ;Option to display as unsigned Int
call dumpreg
call prnline

push 2 ;Option to display as signed integer
call dumpreg
call prnline

The output. Same values, different format;

Code: [Select]
EAX|FFFFFFFD EBX|7FFD4000 ECX|00000000
EDX|00401000 ESI|00000000 EDI|00000000
EBP|0006FF94 ESP|0006FF8C EIP|00401005

EAX|4294967293 EBX|2147303424 ECX|0000000000
EDX|0004198400 ESI|0000000000 EDI|0000000000
EBP|0000458644 ESP|0000458636 EIP|0004198417

EAX|-0000000003 EBX|+2147303424 ECX|+0000000000
EDX|+0004198400 ESI|+0000000000 EDI|+0000000000
EBP|+0000458644 ESP|+0000458636 EIP|+0004198429

Read the header description of "dumpreg".

Enjoy your coding.

Offline stressful

  • Full Member
  • **
  • Posts: 105
  • Country: 00
    • CPU2.0
Re: General Purpose Lib for Extreme Beginners
« Reply #13 on: September 28, 2016, 09:13:33 AM »
[Continue]

The above process is for converting decimal integer to decimal string (1234 to "1234"). The process is exactly the same for octal string, except the divisor is 8. (Valid octal digits are from 0 to 7).

For hex, the divisor is 16 (valid hex digits are from 0,1,2...9,A,B,C,D,E,F). The process is a bit different. Say we have 0x3CCF2

0x3CCF2 / 16 ==> EAX = 0x3CCF, EDX = 2  ==> add 0x30 you get ASCII char '2'
0x3CCF / 16 ==> EAX = 0x3CC, EDX = F  ==> if value is over 9, add 0x37. Else just add 0x30. You get ASCII char 'F'

Code: [Select]
       mov eax,0x3CCF2
       mov ecx,16
getmore:
       xor edx,edx
       div ecx
       add dl,0x30  ;add to everyone
       cmp dl,'9'   ;if ASCII '9' and below
       jbe normal
       add dl,7     ;if alpha hex (A to F)
normal:
       push 0
       call dumpreg
       call halt
       cmp eax,0
       jne getmore

With this series of "dumpreg" output

Code: [Select]
EAX|00003CCF EBX|00323000 ECX|00000010
EDX|00000032 ESI|00401000 EDI|00401000  ;EDX=ASCII '2'
EBP|000DFF94 ESP|000DFF84 EIP|00401019

EAX|000003CC EBX|00323000 ECX|00000010
EDX|00000046 ESI|00401000 EDI|00401000  ;EDX=ASCII 'F'
EBP|000DFF94 ESP|000DFF84 EIP|00401019

EAX|0000003C EBX|00323000 ECX|00000010
EDX|00000043 ESI|00401000 EDI|00401000  ;EDX=ASCII 'C'
EBP|000DFF94 ESP|000DFF84 EIP|00401019

EAX|00000003 EBX|00323000 ECX|00000010
EDX|00000043 ESI|00401000 EDI|00401000  ;EDX=ASCII 'C'
EBP|000DFF94 ESP|000DFF84 EIP|00401019

EAX|00000000 EBX|00323000 ECX|00000010
EDX|00000033 ESI|00401000 EDI|00401000  ;EDX=ASCII '3'
EBP|000DFF94 ESP|000DFF84 EIP|00401019

Next time.

Offline stressful

  • Full Member
  • **
  • Posts: 105
  • Country: 00
    • CPU2.0
Re: General Purpose Lib for Extreme Beginners
« Reply #14 on: October 04, 2016, 12:02:49 PM »
I added full set of Win source so now both Linux and Win sources are on equal terms.

I changed the name of routine "exit" to "exitx" to avoid name clashes with API. Others are not affected.

Enjoy it.

Oct 4th, 2016
« Last Edit: October 24, 2016, 11:49:01 PM by stressful »