| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264 |
- Specifically: for use with gcc with its libraries and gdb
- Specifically: simple nasm syntax using "C" literals
- Specifically: showing an equivalent "C" program
- Generally, for Linux and possibly other Unix on Intel
- Generally, not using 8-bit or 16-bit or 32-bit for anything
- Contents
- Makefile for samples shown below
- hello_64.asm simple Hello World program
- printf1_64.asm basic calling printf
- printf2_64.asm more types for printf
- intarith_64.asm simple integer arithmetic
- fltarith_64.asm simple floating point arithmetic
- fib_64l.asm Print 64-bit fibinachi numbers
- fib_64m.asm Print more like C
- loopint_64.asm simple loop
- testreg_64.asm use rax, eax, ax, ah, al
- shift_64.asm shifting
- ifint_64.asm if then else
- intlogic_64.asm and, or, xor, not
- horner_64.asm Horner method int and double
- call1_64.asm use address of array
- hello_64.asm first sample program
- The nasm source code is hello_64.asm
- The result of the assembly is hello_64.lst
- Running the program produces output hello_64.out
- This program demonstrates basic text output to a file and screen.
- Call is made to C printf
- ; hello_64.asm print a string using printf
- ; Assemble: nasm -f elf64 -l hello_64.lst hello_64.asm
- ; Link: gcc -m64 -o hello_64 hello_64.o
- ; Run: ./hello_64 > hello_64.out
- ; Output: cat hello_64.out
- ; Equivalent C code
- ; // hello.c
- ; #include <stdio.h>
- ; int main()
- ; {
- ; char msg[] = "Hello world\n";
- ; printf("%s\n",msg);
- ; return 0;
- ; }
-
- ; Declare needed C functions
- extern printf ; the C function, to be called
- section .data ; Data section, initialized variables
- msg: db "Hello world", 0 ; C string needs 0
- fmt: db "%s", 10, 0 ; The printf format, "\n",'0'
- section .text ; Code section.
- global main ; the standard gcc entry point
- main: ; the program label for the entry point
- push rbp ; set up stack frame, must be alligned
-
- mov rdi,fmt
- mov rsi,msg
- mov rax,0 ; or can be xor rax,rax
- call printf ; Call C function
- pop rbp ; restore stack
- mov rax,0 ; normal, no error, return value
- ret ; return
-
- printf1_64.asm basic calling printf
- The nasm source code is printf1_64.asm
- The result of the assembly is printf1_64.lst
- The equivalent "C" program is printf1_64.c
- Running the program produces output printf1_64.out
- This program demonstrates basic use of "C" library function printf.
- The equivalent "C" code is shown as comments in the assembly language.
- ; printf1_64.asm print an integer from storage and from a register
- ; Assemble: nasm -f elf64 -l printf1_64.lst printf1_64.asm
- ; Link: gcc -o printf1_64 printf1_64.o
- ; Run: ./printf1_64
- ; Output: a=5, rax=7
- ; Equivalent C code
- ; /* printf1.c print a long int, 64-bit, and an expression */
- ; #include <stdio.h>
- ; int main()
- ; {
- ; long int a=5;
- ; printf("a=%ld, rax=%ld\n", a, a+2);
- ; return 0;
- ; }
- ; Declare external function
- extern printf ; the C function, to be called
- SECTION .data ; Data section, initialized variables
- a: dq 5 ; long int a=5;
- fmt: db "a=%ld, rax=%ld", 10, 0 ; The printf format, "\n",'0'
- SECTION .text ; Code section.
- global main ; the standard gcc entry point
- main: ; the program label for the entry point
- push rbp ; set up stack frame
-
- mov rax,[a] ; put "a" from store into register
- add rax,2 ; a+2 add constant 2
- mov rdi,fmt ; format for printf
- mov rsi,[a] ; first parameter for printf
- mov rdx,rax ; second parameter for printf
- mov rax,0 ; no xmm registers
- call printf ; Call C function
- pop rbp ; restore stack
- mov rax,0 ; normal, no error, return value
- ret ; return
-
- printf2_64.asm more types with printf
- The nasm source code is printf2_64.asm
- The result of the assembly is printf2_64.lst
- The equivalent "C" program is printf2_64.c
- Running the program produces output printf2_64.out
- This program demonstrates general use of "C" library function printf.
- The equivalent "C" code is shown as comments in the assembly language.
- ; printf2_64.asm use "C" printf on char, string, int, long int, float, double
- ;
- ; Assemble: nasm -f elf64 -l printf2_64.lst printf2_64.asm
- ; Link: gcc -m64 -o printf2_64 printf2_64.o
- ; Run: ./printf2_64 > printf2_64.out
- ; Output: cat printf2_64.out
- ;
- ; A similar "C" program printf2_64.c
- ; #include <stdio.h>
- ; int main()
- ; {
- ; char char1='a'; /* sample character */
- ; char str1[]="mystring"; /* sample string */
- ; int len=9; /* sample string */
- ; int inta1=12345678; /* sample integer 32-bit */
- ; long int inta2=12345678900; /* sample long integer 64-bit */
- ; long int hex1=0x123456789ABCD; /* sample hexadecimal 64-bit*/
- ; float flt1=5.327e-30; /* sample float 32-bit */
- ; double flt2=-123.4e300; /* sample double 64-bit*/
- ;
- ; printf("printf2_64: flt2=%e\n", flt2);
- ; printf("char1=%c, srt1=%s, len=%d\n", char1, str1, len);
- ; printf("char1=%c, srt1=%s, len=%d, inta1=%d, inta2=%ld\n",
- ; char1, str1, len, inta1, inta2);
- ; printf("hex1=%lX, flt1=%e, flt2=%e\n", hex1, flt1, flt2);
- ; return 0;
- ; }
- extern printf ; the C function to be called
- SECTION .data ; Data section
- ; format strings for printf
- fmt2: db "printf2: flt2=%e", 10, 0
- fmt3: db "char1=%c, str1=%s, len=%d", 10, 0
- fmt4: db "char1=%c, str1=%s, len=%d, inta1=%d, inta2=%ld", 10, 0
- fmt5: db "hex1=%lX, flt1=%e, flt2=%e", 10, 0
-
- char1: db 'a' ; a character
- str1: db "mystring",0 ; a C string, "string" needs 0
- len: equ $-str1 ; len has value, not an address
- inta1: dd 12345678 ; integer 12345678, note dd
- inta2: dq 12345678900 ; long integer 12345678900, note dq
- hex1: dq 0x123456789ABCD ; long hex constant, note dq
- flt1: dd 5.327e-30 ; 32-bit floating point, note dd
- flt2: dq -123.456789e300 ; 64-bit floating point, note dq
- SECTION .bss
-
- flttmp: resq 1 ; 64-bit temporary for printing flt1
-
- SECTION .text ; Code section.
- global main ; "C" main program
- main: ; label, start of main program
- push rbp ; set up stack frame
- fld dword [flt1] ; need to convert 32-bit to 64-bit
- fstp qword [flttmp] ; floating load makes 80-bit,
- ; store as 64-bit
- mov rdi,fmt2
- movq xmm0, qword [flt2]
- mov rax, 1 ; 1 xmm register
- call printf
- mov rdi, fmt3 ; first arg, format
- mov rsi, [char1] ; second arg, char
- mov rdx, str1 ; third arg, string
- mov rcx, len ; fourth arg, int
- mov rax, 0 ; no xmm used
- call printf
- mov rdi, fmt4 ; first arg, format
- mov rsi, [char1] ; second arg, char
- mov rdx, str1 ; third arg, string
- mov rcx, len ; fourth arg, int
- mov r8, [inta1] ; fifth arg, inta1 32->64
- mov r9, [inta2] ; sixth arg, inta2
- mov rax, 0 ; no xmm used
- call printf
- mov rdi, fmt5 ; first arg, format
- mov rsi, [hex1] ; second arg, char
- movq xmm0, qword [flttmp] ; first double
- movq xmm1, qword [flt2] ; second double
- mov rax, 2 ; 2 xmm used
- call printf
-
- pop rbp ; restore stack
- mov rax, 0 ; exit code, 0=normal
- ret ; main returns to operating system
- intarith_64.asm simple 64-bit integer arithmetic
- The nasm source code is intarith_64.asm
- The result of the assembly is intarith_64.lst
- The equivalent "C" program is intarith_64.c
- Running the program produces output intarith_64.out
- This program demonstrates basic integer arithmetic add, subtract,
- multiply and divide.
- The equivalent "C" code is shown as comments in the assembly language.
- ; intarith_64.asm show some simple C code and corresponding nasm code
- ; the nasm code is one sample, not unique
- ;
- ; compile: nasm -f elf64 -l intarith_64.lst intarith_64.asm
- ; link: gcc -m64 -o intarith_64 intarith_64.o
- ; run: ./intarith_64 > intarith_64.out
- ;
- ; the output from running intarith_64.asm and intarith.c is:
- ; c=5 , a=3, b=4, c=5
- ; c=a+b, a=3, b=4, c=7
- ; c=a-b, a=3, b=4, c=-1
- ; c=a*b, a=3, b=4, c=12
- ; c=c/a, a=3, b=4, c=4
- ;
- ;The file intarith.c is:
- ; /* intarith.c */
- ; #include <stdio.h>
- ; int main()
- ; {
- ; long int a=3, b=4, c;
- ; c=5;
- ; printf("%s, a=%ld, b=%ld, c=%ld\n","c=5 ", a, b, c);
- ; c=a+b;
- ; printf("%s, a=%ld, b=%ld, c=%ld\n","c=a+b", a, b, c);
- ; c=a-b;
- ; printf("%s, a=%ld, b=%ld, c=%ld\n","c=a-b", a, b, c);
- ; c=a*b;
- ; printf("%s, a=%ld, b=%ld, c=%ld\n","c=a*b", a, b, c);
- ; c=c/a;
- ; printf("%s, a=%ld, b=%ld, c=%ld\n","c=c/a", a, b, c);
- ; return 0;
- ; }
- extern printf ; the C function to be called
- %macro pabc 1 ; a "simple" print macro
- section .data
- .str db %1,0 ; %1 is first actual in macro call
- section .text
- mov rdi, fmt4 ; first arg, format
- mov rsi, .str ; second arg
- mov rdx, [a] ; third arg
- mov rcx, [b] ; fourth arg
- mov r8, [c] ; fifth arg
- mov rax, 0 ; no xmm used
- call printf ; Call C function
- %endmacro
-
- section .data ; preset constants, writable
- a: dq 3 ; 64-bit variable a initialized to 3
- b: dq 4 ; 64-bit variable b initializes to 4
- fmt4: db "%s, a=%ld, b=%ld, c=%ld",10,0 ; format string for printf
-
- section .bss ; uninitialized space
- c: resq 1 ; reserve a 64-bit word
- section .text ; instructions, code segment
- global main ; for gcc standard linking
- main: ; label
- push rbp ; set up stack
- lit5: ; c=5;
- mov rax,5 ; 5 is a literal constant
- mov [c],rax ; store into c
- pabc "c=5 " ; invoke the print macro
-
- addb: ; c=a+b;
- mov rax,[a] ; load a
- add rax,[b] ; add b
- mov [c],rax ; store into c
- pabc "c=a+b" ; invoke the print macro
-
- subb: ; c=a-b;
- mov rax,[a] ; load a
- sub rax,[b] ; subtract b
- mov [c],rax ; store into c
- pabc "c=a-b" ; invoke the print macro
-
- mulb: ; c=a*b;
- mov rax,[a] ; load a (must be rax for multiply)
- imul qword [b] ; signed integer multiply by b
- mov [c],rax ; store bottom half of product into c
- pabc "c=a*b" ; invoke the print macro
-
- diva: ; c=c/a;
- mov rax,[c] ; load c
- mov rdx,0 ; load upper half of dividend with zero
- idiv qword [a] ; divide double register edx rax by a
- mov [c],rax ; store quotient into c
- pabc "c=c/a" ; invoke the print macro
- pop rbp ; pop stack
- mov rax,0 ; exit code, 0=normal
- ret ; main returns to operating system
- fltarith_64.asm simple floating point arithmetic
- The nasm source code is fltarith_64.asm
- The result of the assembly is fltarith_64.lst
- The equivalent "C" program is fltarith_64.c
- Running the program produces output fltarith_64.out
- This program demonstrates basic floating point add, subtract,
- multiply and divide.
- The equivalent "C" code is shown as comments in the assembly language.
- ; fltarith_64.asm show some simple C code and corresponding nasm code
- ; the nasm code is one sample, not unique
- ;
- ; compile nasm -f elf64 -l fltarith_64.lst fltarith_64.asm
- ; link gcc -m64 -o fltarith_64 fltarith_64.o
- ; run ./fltarith_64 > fltarith_64.out
- ;
- ; the output from running fltarith and fltarithc is:
- ; c=5.0, a=3.000000e+00, b=4.000000e+00, c=5.000000e+00
- ; c=a+b, a=3.000000e+00, b=4.000000e+00, c=7.000000e+00
- ; c=a-b, a=3.000000e+00, b=4.000000e+00, c=-1.000000e+00
- ; c=a*b, a=3.000000e+00, b=4.000000e+00, c=1.200000e+01
- ; c=c/a, a=3.000000e+00, b=4.000000e+00, c=4.000000e+00
- ; a=i , a=8.000000e+00, b=1.600000e+01, c=1.600000e+01
- ; a<=b , a=8.000000e+00, b=1.600000e+01, c=1.600000e+01
- ; b==c , a=8.000000e+00, b=1.600000e+01, c=1.600000e+01
- ;The file fltarith.c is:
- ; #include <stdio.h>
- ; int main()
- ; {
- ; double a=3.0, b=4.0, c;
- ; long int i=8;
- ;
- ; c=5.0;
- ; printf("%s, a=%e, b=%e, c=%e\n","c=5.0", a, b, c);
- ; c=a+b;
- ; printf("%s, a=%e, b=%e, c=%e\n","c=a+b", a, b, c);
- ; c=a-b;
- ; printf("%s, a=%e, b=%e, c=%e\n","c=a-b", a, b, c);
- ; c=a*b;
- ; printf("%s, a=%e, b=%e, c=%e\n","c=a*b", a, b, c);
- ; c=c/a;
- ; printf("%s, a=%e, b=%e, c=%e\n","c=c/a", a, b, c);
- ; a=i;
- ; b=a+i;
- ; i=b;
- ; c=i;
- ; printf("%s, a=%e, b=%e, c=%e\n","c=c/a", a, b, c);
- ; if(ab ", a, b, c);
- ; if(b==c)printf("%s, a=%e, b=%e, c=%e\n","b==c ", a, b, c);
- ; else printf("%s, a=%e, b=%e, c=%e\n","b!=c ", a, b, c);
- ; return 0;
- ; }
- extern printf ; the C function to be called
- %macro pabc 1 ; a "simple" print macro
- section .data
- .str db %1,0 ; %1 is macro call first actual parameter
- section .text
- ; push onto stack backwards
- mov rdi, fmt ; address of format string
- mov rsi, .str ; string passed to macro
- movq xmm0, qword [a] ; first floating point in fmt
- movq xmm1, qword [b] ; second floating point
- movq xmm2, qword [c] ; third floating point
- mov rax, 3 ; 3 floating point arguments to printf
- call printf ; Call C function
- %endmacro
-
- section .data ; preset constants, writable
- a: dq 3.0 ; 64-bit variable a initialized to 3.0
- b: dq 4.0 ; 64-bit variable b initializes to 4.0
- i: dq 8 ; a 64 bit integer
- five: dq 5.0 ; constant 5.0
- fmt: db "%s, a=%e, b=%e, c=%e",10,0 ; format string for printf
-
- section .bss ; uninitialized space
- c: resq 1 ; reserve a 64-bit word
- section .text ; instructions, code segment
- global main ; for gcc standard linking
- main: ; label
- push rbp ; set up stack
- lit5: ; c=5.0;
- fld qword [five] ; 5.0 constant
- fstp qword [c] ; store into c
- pabc "c=5.0" ; invoke the print macro
-
- addb: ; c=a+b;
- fld qword [a] ; load a (pushed on flt pt stack, st0)
- fadd qword [b] ; floating add b (to st0)
- fstp qword [c] ; store into c (pop flt pt stack)
- pabc "c=a+b" ; invoke the print macro
-
- subb: ; c=a-b;
- fld qword [a] ; load a (pushed on flt pt stack, st0)
- fsub qword [b] ; floating subtract b (to st0)
- fstp qword [c] ; store into c (pop flt pt stack)
- pabc "c=a-b" ; invoke the print macro
-
- mulb: ; c=a*b;
- fld qword [a] ; load a (pushed on flt pt stack, st0)
- fmul qword [b] ; floating multiply by b (to st0)
- fstp qword [c] ; store product into c (pop flt pt stack)
- pabc "c=a*b" ; invoke the print macro
-
- diva: ; c=c/a;
- fld qword [c] ; load c (pushed on flt pt stack, st0)
- fdiv qword [a] ; floating divide by a (to st0)
- fstp qword [c] ; store quotient into c (pop flt pt stack)
- pabc "c=c/a" ; invoke the print macro
- intflt: ; a=i;
- fild dword [i] ; load integer as floating point
- fst qword [a] ; store the floating point (no pop)
- fadd st0 ; b=a+i; 'a' as 'i' already on flt stack
- fst qword [b] ; store sum (no pop) 'b' still on stack
- fistp dword [i] ; i=b; store floating point as integer
- fild dword [i] ; c=i; load again from ram (redundant)
- fstp qword [c]
- pabc "a=i " ; invoke the print macro
- cmpflt: fld dword [b] ; into st0, then pushed to st1
- fld dword [a] ; in st0
- fcomip st0,st1 ; a compare b, pop a
- jg cmpfl2
- pabc "a<=b "
- jmp cmpfl3
- cmpfl2:
- pabc "a>b "
- cmpfl3:
- fld dword [c] ; should equal [b]
- fcomip st0,st1
- jne cmpfl4
- pabc "b==c "
- jmp cmpfl5
- cmpfl4:
- pabc "b!=c "
- cmpfl5:
- pop rbp ; pop stack
- mov rax,0 ; exit code, 0=normal
- ret ; main returns to operating system
- fib_64l.asm print 64-bit fib numbers
- The nasm source code is fib_64l.asm
- The result of the assembly is fib_64l.lst
- The equivalent "C" program is fib.c
- Running the program produces output fib_64l.out
- The nasm source code, like C, is fib_64m.asm
- The result of the assembly is fib_64m.lst
- Running the program produces output fib_64m.out
- Note: output may go negative when size of numbers
- exceed 63-bits without sign. Wrong results with overflow.
- This program demonstrates a loop, saving state between calls.
- First, the 64-bit C program:
- // fib.c same as computation as fib_64m.asm similar fib_64l.asm
- #include <stdio.h>
- int main(int argc, char *argv[])
- {
- long int c = 95; // loop counter
- long int a = 1; // current number, becomes next
- long int b = 2; // next number, becomes sum a+b
- long int d; // temp
- for(c=c; c!=0; c--)
- {
- printf("%21ld\n",a);
- d = a;
- a = b;
- b = d+b;
- }
- return 0;
- }
- Now, the first 64-bit assembly language implementation
- ; fib_64l.asm using 64 bit registers to implement fib.c
- global main
- extern printf
- section .data
- format: db '%15ld', 10, 0
- title: db 'fibinachi numbers', 10, 0
-
- section .text
- main:
- push rbp ; set up stack
- mov rdi, title ; arg 1 is a pointer
- mov rax, 0 ; no vector registers in use
- call printf
- mov rcx, 95 ; rcx will countdown from 52 to 0
- mov rax, 1 ; rax will hold the current number
- mov rbx, 2 ; rbx will hold the next number
- print:
- ; We need to call printf, but we are using rax, rbx, and rcx.
- ; printf may destroy rax and rcx so we will save these before
- ; the call and restore them afterwards.
- push rax ; 32-bit stack operands are not encodable
- push rcx ; in 64-bit mode, so we use the "r" names
- mov rdi, format ; arg 1 is a pointer
- mov rsi, rax ; arg 2 is the current number
- mov eax, 0 ; no vector registers in use
- call printf
- pop rcx
- pop rax
- mov rdx, rax ; save the current number
- mov rax, rbx ; next number is now current
- add rbx, rdx ; get the new next number
- dec rcx ; count down
- jnz print ; if not done counting, do some more
- pop rbp ; restore stack
- mov rax, 0 ; normal exit
- ret
- Now an implementation closer to C, storing variables
- ; fib_64m.asm using 64 bit memory more like C code
- ; // fib.c same as computation as fib_64m.asm
- ; #include
- ; int main(int argc, char *argv[])
- ; {
- ; long int c = 95; // loop counter
- ; long int a = 1; // current number, becomes next
- ; long int b = 2; // next number, becomes sum a+b
- ; long int d; // temp
- ; printf("fibinachi numbers\n");
- ; for(c=c; c!=0; c--)
- ; {
- ; printf("%21ld\n",a);
- ; d = a;
- ; a = b;
- ; b = d+b;
- ; }
- ; }
- global main
- extern printf
- section .bss
- d: resq 1 ; temp unused, kept in register rdx
-
- section .data
- c: dq 95 ; loop counter
- a: dq 1 ; current number, becomes next
- b: dq 2 ; next number, becomes sum a+b
- format: db '%15ld', 10, 0
- title: db 'fibinachi numbers', 10, 0
-
- section .text
- main:
- push rbp ; set up stack
- mov rdi, title ; arg 1 is a pointer
- mov rax, 0 ; no vector registers in use
- call printf
- print:
- ; We need to call printf, but we are using rax, rbx, and rcx.
- mov rdi, format ; arg 1 is a pointer
- mov rsi,[a] ; arg 2 is the current number
- mov rax, 0 ; no vector registers in use
- call printf
- mov rdx,[a] ; save the current number, in register
- mov rbx,[b] ;
- mov [a],rbx ; next number is now current, in ram
- add rbx, rdx ; get the new next number
- mov [b],rbx ; store in ram
- mov rcx,[c] ; get loop count
- dec rcx ; count down
- mov [c],rcx ; save in ram
- jnz print ; if not done counting, do some more
- pop rbp ; restore stack
- mov rax, 0 ; normal exit
- ret ; return to operating system
- loopint_64.asm simple loop
- The nasm source code is loopint_64.asm
- The result of the assembly is loopint_64.lst
- The equivalent "C" program is loopint_64.c
- Running the program produces output loopint_64.out
- This program demonstrates basic loop assembly language
- ; loopint_64.asm code loopint.c for nasm
- ; /* loopint_64.c a very simple loop that will be coded for nasm */
- ; #include <stdio.h>
- ; int main()
- ; {
- ; long int dd1[100]; // 100 could be 3 gigabytes
- ; long int i; // must be long for more than 2 gigabytes
- ; dd1[0]=5; /* be sure loop stays 1..98 */
- ; dd1[99]=9;
- ; for(i=1; i<99; i++) dd1[i]=7;
- ; printf("dd1[0]=%ld, dd1[1]=%ld, dd1[98]=%ld, dd1[99]=%ld\n",
- ; dd1[0], dd1[1], dd1[98],dd1[99]);
- ; return 0;
- ;}
- ; execution output is dd1[0]=5, dd1[1]=7, dd1[98]=7, dd1[99]=9
-
- section .bss
- dd1: resq 100 ; reserve 100 long int
- i: resq 1 ; actually unused, kept in register
- section .data ; Data section, initialized variables
- fmt: db "dd1[0]=%ld, dd1[1]=%ld, dd1[98]=%ld, dd1[99]=%ld",10,0
-
- extern printf ; the C function, to be called
- section .text
- global main
- main: push rbp ; set up stack
- mov qword [dd1],5 ; dd1[0]=5; memory to memory
- mov qword [dd1+99*8],9 ; dd1[99]=9; indexed 99 qword
- mov rdi, 1*8 ; i=1; index, will move by 8 bytes
- loop1: mov qword [dd1+rdi],7 ; dd1[i]=7;
- add rdi, 8 ; i++; 8 bytes
- cmp rdi, 8*99 ; i<99
- jne loop1 ; loop until incremented i=99
-
- mov rdi, fmt ; pass address of format
- mov rsi, qword [dd1] ; dd1[0] first list parameter
- mov rdx, qword [dd1+1*8] ; dd1[1] second list parameter
- mov rcx, qword [dd1+98*8] ; dd1[98] third list parameter
- mov r8, qword [dd1+99*8] ; dd1[99] fourth list parameter
- mov rax, 0 ; no xmm used
- call printf ; Call C function
- pop rbp ; restore stack
- mov rax,0 ; normal, no error, return value
- ret ; return 0;
- testreg_64.asm use rax, eax, ax, ah, al
- The nasm source code is testreg_64.asm
- The result of the assembly is testreg_64.lst
- This program demonstrates basic use of registers in assembly language
- ; testreg_64.asm test what register names can be used
- ;
- ; compile: nasm -f elf64 -l testreg_64.lst testasm_64.asm
- ; link: gcc -o testreg_64 testreg_64.o
- ; run: ./testreg # may get segfault or other error
- ;
- section .data ; preset constants, writable
- aa8: db 8 ; 8-bit
- aa16: dw 16 ; 16-bit
- aa32: dd 32 ; 32-bit
- aa64: dq 64 ; 64-bit
-
- section .bss
- bb16: resw 16
-
- section .rodata
- cc16: db 8
-
- section .text ; instructions, code segment
- global main ; for gcc standard linking
- main: ; label
- push rbp ; set up stack
-
- mov rax,[aa64] ; five registers in RAX
- mov eax,[aa32] ; four registers in EAX
- mov ax,[aa16]
- mov ah,[aa8]
- mov al,[aa8]
- mov RAX,[aa64] ; upper case register names
- mov EAX,[aa32]
- mov AX,[aa16]
- mov AH,[aa8]
- mov AL,[aa8]
-
- mov rbx,[aa64] ; five registers in RBX
- mov ebx,[aa32] ; four registers in EBX
- mov bx,[aa16]
- mov bh,[aa8]
- mov bl,[aa8]
-
- mov rcx,[aa64] ; five registers in RCX
- mov ecx,[aa32] ; four registers in ECX
- mov cx,[aa16]
- mov ch,[aa8]
- mov cl,[aa8]
-
- mov rdx,[aa64] ; five registers in RDX
- mov edx,[aa32] ; four registers in EDX
- mov dx,[aa16]
- mov dh,[aa8]
- mov dl,[aa8]
-
- mov rsi,[aa64] ; three registers in RSI
- mov esi,[aa32] ; two registers in ESI
- mov si,[aa16]
-
- mov rdi,[aa64] ; three registers in RDI
- mov edi,[aa32] ; two registers in EDI
- mov di,[aa16]
- mov rbp,[aa64] ; three registers in RBP
- mov ebp,[aa32] ; two registers in EBP
- mov bp,[aa16]
- mov r8,[aa64] ; just 64-bit r8 .. r15
-
- movq xmm0, qword [aa64] ; xmm registers special
- fld qword [aa64] ; floating point special
-
- ; POPF ; no "mov" on EFLAGS register
- ; PUSHF ; 32 bits on 386 and above
- ; mov rsp,[aa64] ; three registers in RSP
- ; mov esp,[aa32] ; two registers in ESP
- ; mov sp,[aa16] ; don't mess with stack
-
- pop rbp
- mov rax,0 ; exit code, 0=normal
- ret ; main returns to operating system
- ; end testreg_64.asm
- shift_64.asm shifting
- The nasm source code is shift_64.asm
- The result of the assembly is shift_64.lst
- Running the program produces output shift_64.out
- This program demonstrates basic shifting in assembly language
- ; shift_64.asm the nasm code is one sample, not unique
- ;
- ; compile: nasm -f elf64 -l shift_64.lst shift_64.asm
- ; link: gcc -o shift_64 shift_64.o
- ; run: ./shift_64 > shift_64.out
- ;
- ; the output from running shift.asm (zero filled) is:
- ; shl rax,4, old rax=ABCDEF0987654321, new rax=BCDEF09876543210,
- ; shl rax,8, old rax=ABCDEF0987654321, new rax=CDEF098765432100,
- ; shr rax,4, old rax=ABCDEF0987654321, new rax= ABCDEF098765432,
- ; sal rax,8, old rax=ABCDEF0987654321, new rax=CDEF098765432100,
- ; sar rax,4, old rax=ABCDEF0987654321, new rax=FABCDEF098765432,
- ; rol rax,4, old rax=ABCDEF0987654321, new rax=BCDEF0987654321A,
- ; ror rax,4, old rax=ABCDEF0987654321, new rax=1ABCDEF098765432,
- ; shld rdx,rax,8, old rdx:rax=0,ABCDEF0987654321,
- ; new rax=ABCDEF0987654321 rdx= AB,
- ; shl rax,8 , old rdx:rax=0,ABCDEF0987654321,
- ; new rax=CDEF098765432100 rdx= AB,
- ; shrd rdx,rax,8, old rdx:rax=0,ABCDEF0987654321,
- ; new rax=ABCDEF0987654321 rdx=2100000000000000,
- ; shr rax,8 , old rdx:rax=0,ABCDEF0987654321,
- ; new rax= ABCDEF09876543 rdx=2100000000000000,
- extern printf ; the C function to be called
- %macro prt 1 ; old and new rax
- section .data
- .str db %1,0 ; %1 is which shift string
- section .text
- mov rdi, fmt ; address of format string
- mov rsi, .str ; callers string
- mov rdx,rax ; new value
- mov rax, 0 ; no floating point
- call printf ; Call C function
- %endmacro
- %macro prt2 1 ; old and new rax,rdx
- section .data
- .str db %1,0 ; %1 is which shift
- section .text
- mov rdi, fmt2 ; address of format string
- mov rsi, .str ; callers string
- mov rcx, rdx ; new rdx befor next because used
- mov rdx, rax ; new rax
- mov rax, 0 ; no floating point
- call printf ; Call C function
- %endmacro
- section .bss
- raxsave: resq 1 ; save rax while calling a function
- rdxsave: resq 1 ; save rdx while calling a function
-
- section .data ; preset constants, writable
- b64: dq 0xABCDEF0987654321 ; data to shift
- fmt: db "%s, old rax=ABCDEF0987654321, new rax=%16lX, ",10,0 ; format string
- fmt2: db "%s, old rdx:rax=0,ABCDEF0987654321,",10," new rax=%16lX rdx=%16lX, ",10,0
-
- section .text ; instructions, code segment
- global main ; for gcc standard linking
- main: push rbp ; set up stack
-
- shl1: mov rax, [b64] ; data to shift
- shl rax, 4 ; shift rax 4 bits, one hex position left
- prt "shl rax,4 " ; invoke the print macro
- shl4: mov rax, [b64] ; data to shift
- shl rax,8 ; shift rax 8 bits. two hex positions left
- prt "shl rax,8 " ; invoke the print macro
- shr4: mov rax, [b64] ; data to shift
- shr rax,4 ; shift
- prt "shr rax,4 " ; invoke the print macro
- sal4: mov rax, [b64] ; data to shift
- sal rax,8 ; shift
- prt "sal rax,8 " ; invoke the print macro
- sar4: mov rax, [b64] ; data to shift
- sar rax,4 ; shift
- prt "sar rax,4 " ; invoke the print macro
- rol4: mov rax, [b64] ; data to shift
- rol rax,4 ; shift
- prt "rol rax,4 " ; invoke the print macro
- ror4: mov rax, [b64] ; data to shift
- ror rax,4 ; shift
- prt "ror rax,4 " ; invoke the print macro
- shld4: mov rax, [b64] ; data to shift
- mov rdx,0 ; register receiving bits
- shld rdx,rax,8 ; shift
- mov [raxsave],rax ; save, destroyed by function
- mov [rdxsave],rdx ; save, destroyed by function
- prt2 "shld rdx,rax,8"; invoke the print macro
- shla: mov rax,[raxsave] ; restore, destroyed by function
- mov rdx,[rdxsave] ; restore, destroyed by function
- shl rax,8 ; finish double shift, both registers
- prt2 "shl rax,8 "; invoke the print macro
- shrd4: mov rax, [b64] ; data to shift
- mov rdx,0 ; register receiving bits
- shrd rdx,rax,8 ; shift
- mov [raxsave],rax ; save, destroyed by function
- mov [rdxsave],rdx ; save, destroyed by function
- prt2 "shrd rdx,rax,8"; invoke the print macro
- shra: mov rax,[raxsave] ; restore, destroyed by function
- mov rdx,[rdxsave] ; restore, destroyed by function
- shr rax,8 ; finish double shift, both registers
- prt2 "shr rax,8 "; invoke the print macro
- pop rbp ; restore stack
- mov rax,0 ; exit code, 0=normal
- ret ; main returns to operating system
- ifint_64.asm if then else
- The nasm source code is ifint_64.asm
- The result of the assembly is ifint_64.lst
- The equivalent "C" program is ifint_64.c
- Running the program produces output ifint_64.out
- This program demonstrates basic if then else in assembly language
- ; ifint_64.asm code ifint_64.c for nasm
- ; /* ifint_64.c an 'if' statement that will be coded for nasm */
- ; #include <stdio.h>
- ; int main()
- ; {
- ; long int a=1;
- ; long int b=2;
- ; long int c=3;
- ; if(a<b)
- ; printf("true a < b \n");
- ; else
- ; printf("wrong on a < b \n");
- ; if(b>c)
- ; printf("wrong on b > c \n");
- ; else
- ; printf("false b > c \n");
- ; return 0;
- ;}
- ; result of executing both "C" and assembly is:
- ; true a < b
- ; false b > c
-
- global main ; define for linker
- extern printf ; tell linker we need this C function
- section .data ; Data section, initialized variables
- a: dq 1
- b: dq 2
- c: dq 3
- fmt1: db "true a < b ",10,0
- fmt2: db "wrong on a < b ",10,0
- fmt3: db "wrong on b > c ",10,0
- fmt4: db "false b > c ",10,0
- section .text
- main: push rbp ; set up stack
- mov rax,[a] ; a
- cmp rax,[b] ; compare a to b
- jge false1 ; choose jump to false part
- ; a < b sign is set
- mov rdi, fmt1 ; printf("true a < b \n");
- call printf
- jmp exit1 ; jump over false part
- false1: ; a < b is false
- mov rdi, fmt2 ; printf("wrong on a < b \n");
- call printf
- exit1: ; finished 'if' statement
- mov rax,[b] ; b
- cmp rax,[c] ; compare b to c
- jle false2 ; choose jump to false part
- ; b > c sign is not set
- mov rdi, fmt3 ; printf("wrong on b > c \n");
- call printf
- jmp exit2 ; jump over false part
- false2: ; b > c is false
- mov rdi, fmt4 ; printf("false b > c \n");
- call printf
- exit2: ; finished 'if' statement
- pop rbp ; restore stack
- mov rax,0 ; normal, no error, return value
- ret ; return 0;
- intlogic_64.asm bit logic, and, or
- The nasm source code is intlogic_64.asm
- The result of the assembly is intlogic_64.lst
- The equivalent "C" program is intlogic_64.c
- Running the program produces output intlogic_64.out
- This program demonstrates basic and, or, xor, not in assembly language
- ; intlogic_64.asm show some simple C code and corresponding nasm code
- ; the nasm code is one sample, not unique
- ;
- ; compile: nasm -f elf64 -l intlogic_64.lst intlogic_64.asm
- ; link: gcc -m64 -o intlogic_64 intlogic_64.o
- ; run: ./intlogic_64 > intlogic_64.out
- ;
- ; the output from running intlogic_64.asm and intlogic.c is
- ; c=5 , a=3, b=5, c=15
- ; c=a&b;, a=3, b=5, c=1
- ; c=a|b, a=3, b=5, c=7
- ; c=a^b, a=3, b=5, c=6
- ; c=~a , a=3, b=5, c=-4
- ;
- ;The file intlogic_64.c is:
- ; #include <stdio.h>
- ; int main()
- ; {
- ; long int a=3, b=5, c;
- ;
- ; c=15;
- ; printf("%s, a=%ld, b=%ld, c=%ld\n","c=5 ", a, b, c);
- ; c=a&b; /* and */
- ; printf("%s, a=%ld, b=%ld, c=%ld\n","c=a&b;", a, b, c);
- ; c=a|b; /* or */
- ; printf("%s, a=%ld, b=%ld, c=%ld\n","c=a|b", a, b, c);
- ; c=a^b; /* xor */
- ; printf("%s, a=%ld, b=%ld, c=%ld\n","c=a^b", a, b, c);
- ; c=~a; /* not */
- ; printf("%s, a=%ld, b=%ld, c=%d\n","c=~a", a, b, c);
- ; return 0;
- ; }
- extern printf ; the C function to be called
- %macro pabc 1 ; a "simple" print macro
- section .data
- .str db %1,0 ; %1 is first actual in macro call
- section .text
- mov rdi, fmt ; address of format string
- mov rsi, .str ; users string
- mov rdx, [a] ; long int a
- mov rcx, [b] ; long int b
- mov r8, [c] ; long int c
- mov rax, 0 ; no xmm used
- call printf ; Call C function
- %endmacro
-
- section .data ; preset constants, writable
- a: dq 3 ; 64-bit variable a initialized to 3
- b: dq 5 ; 64-bit variable b initializes to 4
- fmt: db "%s, a=%ld, b=%ld, c=%ld",10,0 ; format string for printf
-
- section .bss ; unitialized space
- c: resq 1 ; reserve a 64-bit word
- section .text ; instructions, code segment
- global main ; for gcc standard linking
- main: ; label
- push rbp ; set up stack
-
- lit5: ; c=5;
- mov rax,15 ; 5 is a literal constant
- mov [c],rax ; store into c
- pabc "c=5 " ; invoke the print macro
-
- andb: ; c=a&b;
- mov rax,[a] ; load a
- and rax,[b] ; and with b
- mov [c],rax ; store into c
- pabc "c=a&b;" ; invoke the print macro
-
- orw: ; c=a-b;
- mov rax,[a] ; load a
- or rax,[b] ; logical or with b
- mov [c],rax ; store into c
- pabc "c=a|b" ; invoke the print macro
-
- xorw: ; c=a^b;
- mov rax,[a] ; load a
- xor rax,[b] ; exclusive or with b
- mov [c],rax ; store result in c
- pabc "c=a^b" ; invoke the print macro
-
- notw: ; c=~a;
- mov rax,[a] ; load c
- not rax ; not, complement
- mov [c],rax ; store result into c
- pabc "c=~a " ; invoke the print macro
- pop rbp ; restore stack
- mov rax,0 ; exit code, 0=normal
- ret ; main returns to operating system
- horner_64.asm Horner polynomial evaluation
- The nasm source code is horner_64.asm
- The result of the assembly is horner_64.lst
- The equivalent "C" program is horner_64.c
- Running the program produces output horner_64.out
- This program demonstrates Horner method of evaluating polynomials,
- using both integer and floating point and indexing an array.
- ; horner_64.asm Horners method of evaluating polynomials
- ;
- ; given a polynomial Y = a_n X^n + a_n-1 X^n-1 + ... a_1 X + a_0
- ; a_n is the coefficient 'a' with subscript n. X^n is X to nth power
- ; compute y_1 = a_n * X + a_n-1
- ; compute y_2 = y_1 * X + a_n-2
- ; compute y_i = y_i-1 * X + a_n-i i=3..n
- ; thus y_n = Y = value of polynomial
- ;
- ; in assembly language:
- ; load some register with a_n, multiply by X
- ; add a_n-1, multiply by X, add a_n-2, multiply by X, ...
- ; finishing with the add a_0
- ;
- ; output from execution:
- ; a 6319
- ; aa 6319
- ; af 6.319000e+03
- extern printf
- section .data
- global main
- section .data
- fmta: db "a %ld",10,0
- fmtaa: db "aa %ld",10,0
- fmtflt: db "af %e",10,0
- section .text
- main: push rbp ; set up stack
- ; evaluate an integer polynomial, X=7, using a count
- section .data
- a: dq 2,5,-7,22,-9 ; coefficients of polynomial, a_n first
- X: dq 7 ; X = 7
- ; n=4, 8 bytes per coefficient
- section .text
- mov rax,[a] ; accumulate value here, get coefficient a_n
- mov rdi,1 ; subscript initialization
- mov rcx,4 ; loop iteration count initialization, n
- h3loop: imul rax,[X] ; * X (ignore edx)
- add rax,[a+8*rdi] ; + a_n-i
- inc rdi ; increment subscript
- loop h3loop ; decrement rcx, jump on non zero
- mov rsi, rax ; print rax
- mov rdi, fmta ; format
- mov rax, 0 ; no float
- call printf
- ; evaluate an integer polynomial, X=7, using a count as index
- ; optimal organization of data allows a three instruction loop
-
- section .data
- aa: dq -9,22,-7,5,2 ; coefficients of polynomial, a_0 first
- n: dq 4 ; n=4, 8 bytes per coefficient
- section .text
- mov rax,[aa+4*8] ; accumulate value here, get coefficient a_n
- mov rcx,[n] ; loop iteration count initialization, n
- h4loop: imul rax,[X] ; * X (ignore edx)
- add rax,[aa+8*rcx-8]; + aa_n-i
- loop h4loop ; decrement rcx, jump on non zero
- mov rsi, rax ; print rax
- mov rdi, fmtaa ; format
- mov rax, 0 ; no float
- call printf
- ; evaluate a double floating polynomial, X=7.0, using a count as index
- ; optimal organization of data allows a three instruction loop
-
- section .data
- af: dq -9.0,22.0,-7.0,5.0,2.0 ; coefficients of polynomial, a_0 first
- XF: dq 7.0
- Y: dq 0.0
- N: dd 4
- section .text
- mov rcx,[N] ; loop iteration count initialization, n
- fld qword [af+8*rcx]; accumulate value here, get coefficient a_n
- h5loop: fmul qword [XF] ; * XF
- fadd qword [af+8*rcx-8] ; + aa_n-i
- loop h5loop ; decrement rcx, jump on non zero
- fstp qword [Y] ; store Y in order to print Y
- movq xmm0, qword [Y] ; well, may just mov reg
- mov rdi, fmtflt ; format
- mov rax, 1 ; one float
- call printf
- pop rbp ; restore stack
- mov rax,0 ; normal return
- ret ; return
- call1_64.asm change callers array
- The nasm source code is call1_64.asm
- The main "C" program is test_call1_64.c
- Be safe, header file is call1_64.h
- The equivalent "C" program is call1_64.c
- Running the program produces output test_call1_64.out
- This program demonstrates passing an array to assembly language
- and the assembly language updating the array.
- ; call1_64.asm a basic structure for a subroutine to be called from "C"
- ;
- ; Parameter: long int *L
- ; Result: L[0]=L[0]+3 L[1]=L[1]+4
- global call1_64 ; linker must know name of subroutine
- extern printf ; the C function, to be called for demo
- SECTION .data ; Data section, initialized variables
- fmt1: db "rdi=%ld, L[0]=%ld", 10, 0 ; The printf format, "\n",'0'
- fmt2: db "rdi=%ld, L[1]=%ld", 10, 0 ; The printf format, "\n",'0'
- SECTION .bss
- a: resq 1 ; temp for printing
- SECTION .text ; Code section.
- call1_64: ; name must appear as a nasm label
- push rbp ; save rbp
- mov rbp, rsp ; rbp is callers stack
- push rdx ; save registers
- push rdi
- push rsi
- mov rax,rdi ; first, only, in parameter
- mov [a],rdi ; save for later use
- mov rdi,fmt1 ; format for printf debug, demo
- mov rsi,rax ; first parameter for printf
- mov rdx,[rax] ; second parameter for printf
- mov rax,0 ; no xmm registers
- call printf ; Call C function
- mov rax,[a] ; first, only, in parameter, demo
- mov rdi,fmt2 ; format for printf
- mov rsi,rax ; first parameter for printf
- mov rdx,[rax+8] ; second parameter for printf
- mov rax,0 ; no xmm registers
- call printf ; Call C function
- mov rax,[a] ; add 3 to L[0]
- mov rdx,[rax] ; get L[0]
- add rdx,3 ; add
- mov [rax],rdx ; store sum for caller
- mov rdx,[rax+8] ; get L[1]
- add rdx,4 ; add
- mov [rax+8],rdx ; store sum for caller
- pop rsi ; restore registers
- pop rdi ; in reverse order
- pop rdx
- mov rsp,rbp ; restore callers stack frame
- pop rbp
- ret ; return
|