NASM - The Netwide Assembler
NASM Forum => Example Code => Topic started by: stressful on March 01, 2015, 06:03:05 AM
-
This is a library for 64-bit Linux intended for learners, newbies and any party interested in learning x86_64 assembly language. This library contains various basic routines that provide new learners with a set of enabling and learning tools. This is a basic learning library where transparency and readability is the main objective, rather than optimizations or performance.
The attachment contains 3 files: nsm64.asm, lib64.o and nobjlist.inc and nsm32.asm for 32-bit version. nsm64.asm is the main file while others are optional. lib64.o is the object equivalence to nsm64.asm. It is in non-readable, non-executable object format. nobjlist.inc is required if learners want make their own object file out of the main source file (nsm64.asm). Make sure to backup the original files.
The routines are register-based routines. Arguments are fed into RDI, RSI, RDX, R8. For floating point argument, parameter is fed into XMM0. Return values are placed in either RAX (for integer) or XMM0 (for real). Only "prtch" and "flags" routines have their own different paramater-passing methods. All affected registers are preserved by the callees so that new learners can reduce mistakes and errors at the earliest learning phase. Stack unwinding is done by the callees.
For 32-bit version, arguments are passed to the stack. The first argument is the last one pushed onto the stack.
I tried my best to make the library an ABI-Compliant. That means these routines can also be called from C. It can also be used in its object form and be called from elsewhere (lib64.o).
This library also contains various basic floating-point routines so that new learners do not have to limit themselves to integer-only assembly programming and be less dependant on C library. This promotes more natural assembly learning environment without heavy reliance on third party library.
Each routine has its own descriptions located at their headers. Each describes what a routine does, the arguments required and the return value (if any). I hope learners can get used to the arguments and their types as soon as possible before using the routines.
For learning sake, I intentionally left all the comments blank so that learners should always come back to this forum and participate in more productive discussions and learning activities.
If you found any bug or have suggestions for improvement feel free to contact me. I may also introduce more updates to the original file if time permits.
Happy Coding.
soffianabdulrasad @ gmail . com
EDIT: A new attachment (NASMLIB) contains both nsm64 and nsm32 for single download.
List of routines for 64-bit library (as of April 27th 2015);
prtreg
dumpreg
flags
prtdec
prtdecu
prthex
prtoct
prtbinf
prtbin
fpbin
prtdbl
prtflt
prtstr
prtstrz
prtchar
prtchr
getch
getchr
getstr
getstrz
getint
getdbl
getflt
fpu_stack
fpu_sflag
fpu_cflag
fpu_reg
fpu_copy
str2int
str2dbl
bconv
bitfield
powb10
pow
sqroot
rad2deg
deg2rad
sine
tangent
cosine
atangent
prtxmm
dumpxmm
dumpfxmm
prtxmmq
prtxmmf
sse_flags
rndigit
chr_find
chr_count
str_copy
str_length
str_cmps
str_cmpz
str_reverse
str_alternate
str_tolower
str_toupper
newline
halt
opsize
exitp
exit
One sample code demonstrating various routines of the nsm64;
global _start
section .data
s dq 0xff3e
x dq -34.56
hello db 'Hello World!',0
section .text
_start:
mov rdi,hello
call prtstrz
call newline
mov rdi,[s] ;first argument in RDI
call prtdec ;Display signed integer
call newline
;call getdbl
movq xmm0,[x] ;first argument in xmm0
call prtdbl
call exit
Producing this output:
Hello World!
65342
-34.56000000000000
-
That looks really nice! It may even inspire me to get a 64-bit machine running again so I can try it out. I will almost certainly have comments/questions as I learn from it. Thanks, Soffian!
Best,
Frank
-
It's nothing much Frank. Just some basic routines that I think can help newbies to go through those 'difficult' time. Rather than starting from blank, some basic learning tools should be made available to them to get them going. Nothing fancy though. I am not a good programmer to be honest. Still have lots to learn myself.
-
Although this basic library doesn't use any C routines, they can be called directly from C via its "lib64.o" object file. A demo C program below shows (Note the missing stdio.h statement);
//gcc fromc.c lib64.o -o fromc
extern int chr_count(char *,char);
extern double getdbl();
extern void prtdbl(double);
extern void newline();
extern void prtstrz(char *);
extern void prtdec(int);
int main()
{
double x=0.0;
int count=0;
char *y="Enter a double: ";
char *z="You entered : ";
prtstrz(y);
x=getdbl();
prtstrz(z);
prtdbl(x);
newline();
count=chr_count(y,'e'); //Count 'e' from the string y
prtdec(count);
newline();
return 0;
}
This could be a bit advance, but it demonstrates some basic linking process and how it is important to match the arguments and the return values in accordance to the ABI.
-
This one is for 32-bit linux version library. Almost identical in functionality with the 64-bit version but this one uses stack-based argument passing. Arguments are pushed onto the stack in the particular order (read header descriptions of each). Share, learn and love :D
[Attachment deleted. See Post #1 for download]
-
At times you may want to use floating point literal in your program. To do that, you need to find its hex equivalence. This is how prthex routine can be useful as converter.
global _start
section .data
x dq 567.855
section .text
_start:
mov rdi,[x] ;4081BED70A3D70A4
call prthex
call exit
Now u can use the value displayed as a FP representation in hex format. No need for C or other macro. Saves you lots of time and effort.
-
To access the library via static linking, use the accompanying lib64.o file. One example;
;Compile: nasm -f elf64 test.asm
;Link : ld test.o lib64.o -o test
section .data
hello db 'Hello World!',0ah,0
section .code
global _start
extern prtstrz
extern exit
_start:
mov rdi,hello
call prtstrz ;display 0-ended string
call exit
-
I fixed some embarrassing bugs in prtdbl and prtflt when dealing with 0.0 and -0.0. Sorry ;D
I added 4 new routines dealing mostly with XMM registers;
1) dumpfxmm - view XMM dump in floating format instead of just hex (as in dumpxmm)
2) prtxmmf - view an XMM register as 4 floats
3) prtxmmq - view an XMM register as 2 doubles
4) opsize - Non-XMM routine. To calculate code or data size between 2 labels. Example;
a:
nop
nop
b:
mov rdi,a ;order is not important
mov rsi,b
call opsize ;should produce size of 2
Will update more if I got some more spare time.
Cheers ;D
-
Here i wrote a small conversion program that enables learners to perform a quick base conversion from popular bases (hex, bin, decimal, octal) to another bases up to base 36 (max). This is a command-line program (not part of the library above). This program below also demonstrates basic steps in creating command-line programs.
Sample run;
$ ./baseconv 45h 10 --> convert 45 hex to base 10
$ ./baseconv 10111000111b --> convert 10111000111b binary to base 8 (octal)
$ ./baseconv 26544437654o 30 --> convert one octal number to base 30
$ ./baseconv --> Display help message.
The program;
;Compile: nasm -f elf64 baseconv.asm
;Link : ld baseconv.o -o baseconv
;Run :./baseconv 3ccdeh 5. Convert a hex to base 5
global _start
section .data
errmsg db 'baseconv : 64-bit base converter (integer)',0ah
db 'usage : baseconv <value+suffix> <base>',0ah
db 'example : baseconv 35h 10 - convert 35h to decimal',0ah
db ' : <base> maximum is 36',0ah
db ' : <suffix> - h,d,o,b',0ah
db 'author : soffianabdulrasad @ gmail . com',0ah,0
section .bss
numb resq 1
base resq 1
tmp resb 1
section .code
_start:
mov rbp,rsp
mov rbx,[rbp] ;Number of arguments in RBX
cmp rbx,3 ;If less arguments...
jne .err ; ...show help message
mov rsi,[rbp+16] ;First argument
call atoi ;Convert to integer
mov [numb],rax ;return value in RAX
mov rsi,[rbp+24] ;Second argument
call atoi ;Convert to integer
;--------------------------
.bconv:
mov rbx,rax
mov rax,[numb]
xor rdi,rdi
test rax,rax
jns .start
neg rax
push rax
mov al,'-'
call ch_out
pop rax
.start:
xor rdx,rdx
div rbx
push rdx
test rax,rax
jz .fine
inc rdi
jmp .start
.fine:
pop rax
add al,30h
cmp al,39h
jbe .num
add al,7
.num:
call ch_out
dec rdi
jns .fine
mov al,0ah
call ch_out
jmp .done
;--------------------
.err:
mov rdi,errmsg
mov rcx,-1
xor al,al
repne scasb
mov rdx,-2
sub rdx,rcx
mov edi,1
mov eax,edi
mov rsi,errmsg
syscall
;-------------------
.done:
xor edi,edi
mov eax,60
syscall
ret
;--------------------
atoi:
xor r15,r15
xor rax,rax
xor r8,r8
lodsb
cmp al,'-'
jne .norm
mov r15b,1
.begin:
lodsb
.norm:
test al,al
jz .select
push rax
inc r8
jmp .begin
.select:
pop rax
cmp al,'h'
je .hexadecimal
cmp al,'H'
je .hexadecimal
cmp al,'b'
je .binary
cmp al,'B'
je .binary
cmp al,'o'
je .octal
cmp al,'O'
je .octal
cmp al,'d'
je .decimal
cmp al,'D'
je .decimal
push rax
inc r8
.decimal:
xor r9,r9
pop rax
sub rax,30h
add r9,rax
mov ecx,10
mov ebx,ecx
dec r8
jmp .translate
.hexadecimal:
xor r9,r9
pop rax
cmp al,'a'
jae .smalls
cmp al,'A'
jae .bigs
jmp .proceed
.bigs:
cmp al,'F'
ja .big
.big:
sub rax,7h
jmp .proceed
.smalls:
cmp al,'f'
ja .proceed
.small:
sub rax,27h
.proceed:
sub rax,30h
add r9,rax
mov ecx,16
mov ebx,ecx
dec r8
jmp .translate
.octal:
xor r9,r9
pop rax
sub rax,30h
add r9,rax
mov ecx,8
mov ebx,ecx
dec r8
jmp .translate
.binary:
xor r9,r9
pop rax
sub rax,30h
add r9,rax
mov ecx,2
mov ebx,ecx
dec r8
jmp .translate
.translate:
dec r8
jz .exit
pop rax
cmp rbx,16
jne .proceed1
cmp al,'a'
jae .Smalls
cmp al,'A'
jae .Bigs
jmp .proceed1
.Bigs:
cmp al,'F'
ja .Big
.Big:
sub rax,7h
jmp .proceed1
.Smalls:
cmp al,'f'
ja .proceed1
.Small:
sub rax,27h
.proceed1:
sub rax,30h
mul rcx
add r9,rax
mov rax,rbx
mul rcx
mov rcx,rax
jmp .translate
.exit:
cmp r15b,1
jne .out
neg r9
.out:
mov rax,r9
ret
;--------------------
ch_out:
push rax
push rdi
mov byte[tmp],al
mov rsi,tmp
mov edx,1
mov edi,edx
mov eax,edx
syscall
pop rdi
pop rax
ret
The downloads, plus the executable.
Hope you'll find it helpful and useful.
-
My 1st post. So please understand my lack of knowledge.
So, how do I get the nsm64.asm or nasmlib??????
I see nothing in your post on how to get them
-
Both the 32- and 64-bit versions are zipped as an attachment to the first post in this topic. Post again if you have trouble with it.
Best,
Frank
-
Thank you for the hard work stressful. We are lucky to have you. :D
-
oh.. okay...
in a moment.
-
One year later... LOL. Now I can't even remember how to edit my own post. So this is on a new post :P
This is the latest source for nsm32 and nsm64. Both in source format. Native, low and easy for beginners to follow through and use. These are slightly better and offer more features. Non-ABI compliant.
prnchr
prnchrs
prnchar
prnstr
prnstrz
prnstrd
readch
readchr
readstr
delay
mem_alloc
mem_free
file_new
file_open
file_read
file_write
file_close
file_size
exit
exitp
newline
halt
prnstreg
prnreg
prnregd
prnregdu
dumpreg
dumpregd
dumpregdu
dumpseg
dumpenv
flags
stackview
memview
memviewc
mem_reset
mem_set
mem_copy
mem_load
opsize
opcode
prnint
prnintu
prnhex
prnhexu
prnoct
prnoctu
prnbin
prnbinu
prnbinf
prnbinb
fpbin
fpbind
prndbl
prndble
prndblr
prnflt
prnfltr
prndblx
dblsplit
fpdinfo
fpfinfo
dec2str
dec2stru
hex2str
hex2stru
dbl2str
readint
readflt
readdbl
fpu_stack
fpu_sflag
fpu_cflag
fpu_tag
fpu_reg
fpu_copy
fpu_precision
fpu_round
sse_round
sse_flags
prnxmm
dumpxmm
clearxmm
prnymm
dumpymm
clearymm
prnintd
prnintw
prnintb
str2int
str2dbl
str2flt
dbl2int
int2dbl
rndigit
rndint
isint
digiti
digith
factorial
powint
pow2
iseven
isodd
bconv
bitfield
addf
subf
mulf
divf
pow
sqroot
log10
ln10
deg2rad
rad2deg
sine
tangent
cosine
sincos
atangent
chr_isdigit
chr_isalpha
chr_isupper
chr_islower
chr_toupper
chr_tolower
chr_chcase
chr_find
chr_count
chr_shuffle
ascii
str_copy
str_length
str_cmpz
str_cmp
str_toupper
str_tolower
str_reverse
str_trim
str_wordcnt
str_token
str_find
str_findz
str_appendz
str_append
sort_byte
sort_int
sort_dbl
sort_dblx
sort_flt
aprndbl
aprndblx
aprnflt
aprnint
The attachment (Update May 6th, 2016):
-
August 14th, 2016 Update:
.Made some minor improvement to the library and added 7 more routines.
.Now the library has two different formats. One is in source format and the other is in static object format for your convenience.
.Included some new documentations in both folders for easy reference.
Since I can't retract/update the older uploads/attachments like the above, you should always download the latest version like this one and ignore the older ones.
This is final revision. Enjoy your learning of assembly programming.
;List for 64-bit routines
prnchr
prnchrs
prnchar
prnstr
prnstrz
prnstrd
readch
readchr
readstr
delay
mem_alloc
mem_free
file_new
file_open
file_read
file_write
file_close
file_size
exit
exitp
newline
halt
prnstreg
prnreg
prnregd
prnregdu
dumpreg
dumpregd
dumpregdu
dumpseg
dumpenv
flags
stackview
memview
memviewc
mem_reset
mem_set
mem_copy
mem_load
opsize
opcode
prnint
prnintu
prnhex
prnhexu
prnoct
prnoctu
prnbin
prnbinu
prnbinf
prnbinb
fpbin
fpbind
prndbl
prndble
prndblr
prnflt
prnfltr
prndblx
dblsplit
fpdinfo
fpfinfo
dec2str
dec2stru
hex2str
hex2stru
dbl2str
readint
readflt
readdbl
fpu_stack
fpu_sflag
fpu_cflag
fpu_tag
fpu_reg
fpu_copy
fpu_precision
fpu_round
sse_round
sse_flags
prnmmx
dumpmmx
prnxmm
dumpxmm
clearxmm
prnymm
dumpymm
clearymm
prnintd
prnintw
prnintb
str2int
str2dbl
str2flt
dbl2int
int2dbl
rndigit
rndint
isint
digiti
digith
digiti_count
digiti_countu
digith_count
digith_countu
factorial
powint
pow2
iseven
isodd
bconv
bitfield
addf
subf
mulf
divf
fcalc
pow
sqroot
log10
ln10
deg2rad
rad2deg
sine
tangent
cosine
sincos
atangent
chr_isdigit
chr_isalpha
chr_isupper
chr_islower
chr_toupper
chr_tolower
chr_chcase
chr_find
chr_count
chr_shuffle
ascii
str_copy
str_length
str_cmpz
str_cmp
str_toupper
str_tolower
str_reverse
str_trim
str_wordcnt
str_token
str_find
str_findz
str_appendz
str_append
sort_byte
sort_int
sort_dbl
sort_dblx
sort_flt
aprndbl
aprndblx
aprnflt
aprnint
-
I uploaded the latest version of the library (August 7th update). Please ignore the previous uploads and use this one instead.
Fixed some minor bugs, added some more routines, improved the documentation and also included the static object version for beginners convenience.
If there's no more fatal bugs then take this as the final version.
Good luck.
-
Sep 14th, 2016 Update
Revision 2.6. Some changes
- change "newline" to "prnline" to avoid potential nameclash with other foreign libs
- "dumpreg" now takes one argument. Other dumpregxx are deleted.
- introduced few more routines
- Documentation format is open and configurable to your needs
Please ignore the other attachments and pick this latest versions.
LIST OF ROUTINES
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(167) Descriptions
------------------------------------------------------------------
prnline - Print a new line
halt - Pause screen
prnstreg(1) - Display short string off RAX
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.
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.
digitprob(2)/1 - Extract digit from a signed integer
digitprobu(2)/1 - Extract digit from a signed integer
digithprob(2)/1 - Extract digit from a signed integer
digithprobu(2)/1- Extract digit from a signed integer
digitscan(2)/1 - Extract digit from a signed integer
digitscanu(2)/1 - Extract digit from a signed integer
digithscan(2)/1 - Extract digit from a signed integer
digithscanu(2)/1- Extract digit from a signed integer
digitcount(1)/1 - Extract digit from a signed integer
digitcountu(1)/1 - Extract digit from a signed integer
digithcount(1)/1 - Extract digit from a signed integer
digithcountu(1)/1- Extract digit from a signed integer
rndigit(1)/1 - Get one random digit of normal bases.
rndint(1) - Generate 1 random integer.
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_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.
chr_shuffle(1) - Shuffle a 0-ended string
ascii(1) - Simple ascii byte conversion
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
;----- OS SPECIFICS -----
prnchr(1) - Display char in AL
prnchrs(1) - Display a character from the stack
prnchar(1) - Display a character variable
prnstr(2) - Display string with size
prnstrz(1) - Display 0-ended string
prnstrd(2) - Display delimiter-ended string
readch/1 - Get a char from kboard. Return in AL
readchr(1) - Get a character and save to variable
readstr(1)/1 - Get a string with size
delay(1) - Delay execution in milliseconds.
mem_alloc(1)/1 - Get memory
mem_free(1)/1 - Release memory
timer_start - Start a timer (win only)
timer_stop/1 - Stop a timer (win only)
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
exit - Exit to system
Happy learning and good luck.
-
Updated the library. See previous post.
-
that's cool
-
that's cool
Thanks for the kind words. Please use the updated version (Revision 2.6) here.
https://forum.nasm.us/index.php?topic=2269.msg10727#msg10727
Thanks.
-
Perfect for newbies like me, thanks ! :)