nasm programming language
Learn from examples
1. Program to output a string, integer, and floating point
exnl1.asm source code
;; exnl1.asm example print string, integer, float
;;; semicolon, one or more is comment
; sections contain specific information:
; section .data is for initialized variables, strings, arrays, etc.
; section .rodata is for initialized constants, protected, not changeable
; section .bss is block starting symbol for uninitialized arrays, etc.
; section .txt is last, for program instructions, define macros before use
; print using printf (everything same as C)
extern printf ; the C function, to be called
section .data ; Data section, initialized variables
msg: db "nasm exnl1.asm running", 0 ; C string needs 0
msg2: db "exnl1.asm finished", 0
fmt: db "%s", 10, 0 ; The printf format, "\n",'0' string format
i: dq 9999 ; integer as quad word
fmti: db "i = %d", 10, 0 ; integer format
x: dq 37.1 ; floating point as quad word
fmtx: db "x = %f", 10, 0 ; floating point format
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 aligned
; print string
mov rdi,fmt ; address of format, required register rdi
mov rsi,msg ; address of data
mov rax,0 ; or can be xor rax,rax
call printf ; Call C function
; print integer
mov rdi,fmti ; address of format, required register rdi
mov rsi,[i] ; value of data
mov rax,0 ; number of float to print
call printf ; Call C function
; print float or double
movq xmm0, qword[x] ; value of data
mov rdi,fmtx ; address of format, required register rdi
mov rax,1 ; number of float to print
call printf ; Call C function
mov rdi,fmt
mov rsi,msg2
mov rax,0
call printf
pop rbp ; restore stack
mov rax,0 ; normal, no error, return value
ret ; return
Execution output:
nasm exnl1.asm running
i = 9999
x = 37.100000
exnl1.asm finished
Many many registers available, see
testreg_64.asm source code
2. commands to execute the source code
at a minimum, Windows, Linux, MacOSX.
Windows: use nmake or nasm.bat
??? exnl1.asm _main rather than main
Linux:
Assemble: nasm -f elf64 -l exnl1.lst exnl1.asm
Link: gcc -m64 -o exnl1 exnl1.o
Run: exnl1 > exnl1.out
Output: cat exnl1.out
Clean: rm -f exnl1.o
MacOSX
??? exnl1.asm _main rather than main
Sample Makefile:
# Makefile for nasm exnl1.out file
all: exnl1.out # can have many .out
exnl1.out : exnl1.asm
nasm -f elf64 -l exnl1.lst exnl1.asm # must use tab
gcc -m64 -o exnl1 exnl1.o
exnl1 > exnl1.out
cat exnl1.out
rm -f exnl1.o # optional exnl1.lst exnl1
3. You must be able to declare variables and arrays
and matrix of various types.
exnl3.asm source code
; exnl3.asm example declare variables, arrays, matrix
extern printf
section .data ; Data section, initialized variables
msg: db "nasm exnl3.asm running", 0 ; C string needs 0
msg2: db "exnl3.asm finished", 0
fmt: db "%s", 10, 0
i1: db 1 ; byte, 8 bit, integer 1
i2: dw 2 ; word, 16 bit, integer 2
j3: dd 3, 3.5 ; double word, 32 bit, integer 3, float 3.5
f4: dq 1.1, 1.2, 2.1, 2.2 ; quad word, 64 bit, double 1.1, 1.2, 2.1, 2.2
i3: dq 1, 2, 3 ; quad word, 64 bit, long integers 1, 2, 3
; quad word is 8 bytes (for indexing address)
section .rodata ; read only data, protected
one: dq 1.0 ; can not be changed
section .bss ; block starting symbol for arrays
s1: resb 80 ; 80 characters, bytes, allocated
b2: resw 2 ; 2 words allocated
c5: resd 5 ; 5 double words allocated
a1: resq 3 ; 3 quad words allocated
m1: resq 4 ; 4 quad words, could be 2 by 2 integer matrix
; increment byte address by 4 for each integer
dmat: resq 8 ; could be 2 by 2 matrix of double
; increment byte address by 8 for each double
section .text ; Code section.
global main ; main program required name "main"
main:
push rbp ; set up stack frame, must be aligned
mov rdi,fmt ; address of format, required register rdi
mov rsi,msg ; address of data
mov rax,0 ; or can be xor rax,rax
call printf ; Call C function
mov rdi,fmt ; finished print statement
mov rsi,msg2
mov rax,0
call printf
pop rbp ; restore stack
mov rax,0 ; normal, no error, return value
ret ; return
Execution output:
nasm exnl3.asm running
exnl3.asm finished
3a. more sample code to see other examples:
testreg_64.asm see available registers
intarith_64.asm see integer operations
intarith_64.out output
fltarith_64.asm see float operations
fltarith_64.out output
4. You need to be able to have loops, iteration statements
exnl4.asm source code
; exnl4.asm example loops iteration
extern printf
section .data ; Data section, initialized variables
msg: db "nasm exnl4.asm running", 0 ; C string needs 0
msg2: db "exnl4.asm finished", 0
fmt: db "%s", 10, 0
fmt1: db "iloop i=%d", 10, 0 ; format needs \n 0
n: dq 3 ; for simple loop
fmtfl: db "floop x=%e", 10, 0
xlast: dq 8.0 ; for float loop
xinc: dq 2.0 ; for +2.0
m1: dq 1.1, 1.2, 1.3, 2.1, 2.2, 2.3 ; row major 2 by 3 matrix
m1name: db "m1", 0
ncol1: dq 2
nrow1: dq 3
m2: dq 1.1, 2.1, 3.1, 1.2, 2.2, 3.2 ; coloum major 3 by 2 matrix
m2name: db "m2", 0
ncol2: dq 3
nrow2: dq 2
i8: dq 8
fmtm: db "%s[%d][%d]=%e", 10, 0
fijk: db "i=%d, j=%d, k=%d, l=%d", 10, 0
section .bss
i: resq 1 ; reserve space, 1 is one quad word
j: resq 1
k: resq 1
l: resq 1
x: resq 1 ; float type or any type
section .text ; Code section.
global main
main:
push rbp ; set up stack frame, must be aligned
mov rdi,fmt ; address of format, required register rdi
mov rsi,msg ; address of data
mov rax,0 ; or can be xor rax,rax
call printf ; Call C function
; simple loop
mov rax,0 ; for(i=0 ; i<n; i++)
mov [i],rax ; i=0
loop: ; use i for what you want
mov rdi,fmt1 ; just print i
mov rsi,[i]
mov rax,0
call printf
mov rax,[i] ; safest to keep variable in memory
inc rax ; i++
mov [i],rax
cmp rax,[n] ; i<n
jne loop
; float loop
fld qword [xinc] ; for(x=2.0 x<xlast x=x+xinc)
fstp qword [x] ; x=2.0
floop: ; use x for what you want
mov rdi,fmtfl ; just print x
movq xmm0, qword [x]
mov rax,1
call printf
fld qword [x] ; safest to keep variable in memory
fadd qword [xinc] ; x = x + xinc
fstp qword [x]
fld qword [xlast] ; pushed into st0, then st1
fld qword [x] ; pushed into st0
fcompp ; compare and pop both
; jg floop ; infinite loop
jl floop ; quit first time
; for(i=0; i<nrow; i++) { for(j=0; j<ncol; j++) { print m1[i][j] }}
mov rax,0
mov [i],rax ; i=0
loopi:
mov rax,[i]
mov rbx,0
mov [j],rbx ; j=0
loopj:
mov rax,[i]
mov rbx,[j]
imul qword [ncol1] ; i*ncol1
add rax, rbx ; i*ncol1+j [i][j]
mov [k],rax
imul qword [i8] ; byte address offset
mov [l],rax ; save to memory
mov rdi,fijk ; debug print
mov rsi,[i]
mov rdx,[j]
mov rcx,[k]
mov r8,[l]
mov rax,0
call printf
mov rdi,fmtm ; print matrix
mov rsi,m1name
mov rdx,[i]
mov rcx,[j]
mov rbx,[l] ; set up byte offset
movq xmm0,qword[m1+rbx] ; m1[(i*ncol1+j)*8] byte address
mov rax,1 ; number of floats to print
call printf
mov rbx,[j]
inc rbx ; j++
mov [j],rbx
cmp rbx,[ncol1] ; j<ncol
jne loopj
mov rax,[i]
inc rax ; i++
mov [i],rax
cmp rax,[nrow1] ; i<nrow1
jne loopi
mov rdi,fmt ; exit print
mov rsi,msg2
mov rax,0
call printf
pop rbp ; restore stack
mov rax,0 ; normal, no error, return value
ret ; return
Execution output:
nasm exnl4.asm running
iloop i=0
iloop i=1
iloop i=2
floop x=2.000000e+00
i=0, j=0, k=0, l=0
m1[0][0]=1.100000e+00
i=0, j=1, k=1, l=8
m1[0][1]=1.200000e+00
i=1, j=0, k=2, l=16
m1[1][0]=1.300000e+00
i=1, j=1, k=3, l=24
m1[1][1]=2.100000e+00
i=2, j=0, k=4, l=32
m1[2][0]=2.200000e+00
i=2, j=1, k=5, l=40
m1[2][1]=2.300000e+00
exnl4.asm finished
5. You need if then else conditional statements
exnl5.asm source code
# exnl5.asm example of if then else
; exnl5.asm example if then else
extern printf
section .data ; Data section, initialized variables
msg: db "nasm exnl5.asm running", 0 ; C string needs 0
msg2: db "exnl5.asm finished", 0
msg3: db "if then else on integers", 0
msg4: db "if then else on floats", 0
fmt: db "%s", 10, 0
a: dq 1
b: dq 2
c: dq 3
xyz: dq 4
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
fmt5: db "failed 4==xyz ",10,0
fmt6: db "passed 4==xyz ",10,0
fmt7: db "failed 5>xyz ",10,0
fmt8: db "passed 5>xyz ",10,0
fmt9: db "failed 3<xyz ",10,0
fmt10: db "passed 3<xyz ",10,0
af: dt 1.0
bf: dt 2.0
cf: dt 3.0
fmt1f: db "true af < bf ",10,0
fmt2f: db "wrong on af < bf ",10,0
fmt3f: db "wrong on bf > cf ",10,0
fmt4f: db "false bf > cf ",10,0
section .bss ; unused, except to pop
t: rest 1 ; reserve one space for dt
section .text ; Code section.
global main
main:
push rbp ; set up stack frame, must be aligned
mov rdi,fmt ; address of format, required register rdi
mov rsi,msg ; address of data
mov rax,0 ; or can be xor rax,rax
call printf ; Call C function
mov rdi,fmt ; address of format, required register rdi
mov rsi,msg3 ;
mov rax,0 ;
call printf ;
; 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;
; long int xyz=4;
; 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");
;
; if(4==xyz) goto label1e;
; printf("failed 4==xyz\n");
;label1e: printf("passed 4==xyz\n");
;
; if(5>xyz) goto label1g;
; printf("failed 5>xyz\n");
;label1g: printf("passed 5>xyz\n");
;
; if(3<xyz) goto label1l;
; printf("failed 3<xyz\n");
;label1l: printf("passed 3<xyz\n");
;
; return 0;
;}
; result of executing both "C" and assembly is:
; true a < b
; false b > c
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");
mov rax,0
call printf
jmp exit1 ; jump over false part
false1: ; a < b is false
mov rdi, fmt2 ; printf("wrong on a < b \n");
mov rax,0
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");
mov rax,0
call printf
jmp exit2 ; jump over false part
false2: ; b > c is false
mov rdi, fmt4 ; printf("false b > c \n");
mov rax,0
call printf
exit2: ; finished 'if' statement
mov rax,4
cmp rax,[xyz] ; if(4==xyz) goto label1e;
je label1e
mov rdi, fmt5
mov rax,0
call printf
label1e:mov rdi, fmt6
mov rax,0
call printf
mov rax,5
cmp rax,[xyz] ; if(5>xyz) goto label1g;
jg label1g
mov rdi, fmt7
mov rax,0
call printf
label1g:mov rdi, fmt8
mov rax,0
call printf
mov rax,3
cmp rax,[xyz] ; if(3<xyz) goto label1l;
jl label1l
mov rdi, fmt9
mov rax,0
call printf
label1l:mov rdi, fmt10
mov rax,0
call printf
mov rdi,fmt ; address of format, required register rdi
mov rsi,msg4 ;
mov rax,0 ;
call printf ;
; code ifflt_64.c for nasm
; /* ifflt_64.c an 'if' statement that will be coded for nasm */
; #include <stdio.h>
; int main()
; {
; double af=1.0;
; double bf=2.0;
; double cf=3.0;
; if(af<bf)
; printf("true af < bf \n");
; else
; printf("wrong on af < bf \n");
; if(b>c)
; printf("wrong on bf > cf \n");
; else
; printf("false bf > cf \n");
; return 0;
;}
; result of executing both "C" and assembly is:
; true af < bf
; false bf > cf
fld tword [bf] ; bf into st0
fld tword [af] ; af into st0, pushes b into st1
fcompp ; compare and pop both
; fcomip st0,st1 ; compare af to bf, pop af
; fstp tword [t] ; just to pop bf
jl false1f ; choose jump to false part
; af < bf sign is set
mov rdi, fmt1f ; printf("true af < bf \n");
mov rax, 0
call printf
jmp exit1f ; jump over false part
false1f: ; af < bf is false
mov rdi, fmt2f ; printf("wrong on af < bf \n");
mov rax, 0
call printf
exit1f: ; finished 'if' statement
fld tword [cf] ; cf into st0
fld tword [bf] ; bf into st0, pushes cf into st1
fcompp ; compare and pop both
; fcomip st0,st1 ; compare bf to cf, pop bf
; fstp tword [t] ; just to pop cf
jg false2f ; choose jump to false part
; bf > cf sign is not set
mov rdi, fmt3f ; printf("wrong on bf > cf \n");
mov rax, 0
call printf
jmp exit2f ; jump over false part
false2f: ; bf > cf is false
mov rdi, fmt4f ; printf("false bf > cf \n");
mov rax, 0
call printf
exit2f: ; finished 'if' statement
mov rdi,fmt ; print finished
mov rsi,msg2
mov rax,0
call printf
pop rbp ; restore stack
mov rax,0 ; normal, no error, return value
ret ; return
Execution output:
nasm exnl5.asm running
if then else on integers
true a < b
false b > c
passed 4==xyz
passed 5>xyz
passed 3<xyz
if then else on floats
true af < bf
false bf > cf
exnl5.asm finished
6. You need to be able to create functions, procedures,
subroutines.
exnl6.asm source code
; exnl6.asm example declare and call funstions and procedures
extern printf
section .data ; Data section, initialized variables
msg: db "nasm exnl6.asm running", 0 ; C string needs 0
msg2: db "exnl6.asm finished", 0
fmt: db "%s", 10, 0
fmti db "diff = %d", 10, 0
fmtf: db "ssq = %f", 10, 0
af: dq 1.1
bf: dq 3.3
ai: dq 13
bi: dq 27
section .bss ; variable and array section
cf: resq 1
ci: resq 1
tmp: resq 1
section .text ; Code section.
global main
main:
push rbp ; set up stack frame, must be aligned
mov rdi,fmt ; address of format, required register rdi
mov rsi,msg ; address of data
mov rax,0 ; or can be xor rax,rax
call printf ; Call C function
call jprt ; call no parameter procedure
mov rdi,[ai] ; first integer parameter value
mov rsi,[bi] ; second integer paramenter value
call diff ; function return in rax
mov [tmp],rax ; save result and print result using macro
; print
mov rdi, fmti ; address of format string
mov rsi, [tmp] ; int value
mov rax, 0 ; 0 floating point arguments to printf
call printf ; Call C function
movq xmm0, qword[af] ; first double parameter value
movq xmm1, qword[bf] ; second double parameter value
call ssq ; function return in xmm2
movq qword[tmp], xmm2 ; save result and print result
; print
mov rdi, fmtf ; address of format string
movq xmm0, qword[tmp] ; first floating point in fmt
mov rax, 1 ; 1 floating point arguments to printf
call printf ; Call C function
mov rdi,fmt
mov rsi,msg2
mov rax,0
call printf
pop rbp ; restore stack
mov rax,0 ; normal, no error, return value
ret ; return
; function definitions, called above
section .data ; Data section
jprthi: db "Hi from jprt", 10, 0
section .bss ; variables, arrays space
tmpf: resq 1 ; temp space
parf1: resq 1
parf2: resq 1
section .text ; Code section.
jprt: mov rdi,fmt ; no parameters
mov rsi,jprthi
mov rax,0
call printf
ret ; end jprt
diff: mov rax,rdi ; rdi first integer parameter
sub rax,rsi ; rsi second integer parameter
ret ; function result in rax
ssq: movq qword[parf1], xmm0 ; save first parameter
movq qword[parf1], xmm1 ; save second parameter
fld qword[parf1] ; first parameter
fmul qword[parf1] ; squared
fstp qword[tmpf] ; saved
fld qword[parf2] ; second parameter
fmul qword[parf1] ; squared
fadd qword[tmpf] ; sum
fstp qword[tmpf] ; return value
movq xmm2, qword[tmpf] ; return in register
ret
Execution output:
nasm exnl6.asm running
Hi from jprt
diff = -14
ssq = 10.890000
exnl6.asm finished
7. You need to be able to read and write files in various formats.
exnl7.asm source code
;; exnl7.asm 32 bit read and print file
;; Test _read and _write system calls windows, read, write linux
;; removed _ for linux
;;
;; nasm -f elf -Wall -Werror exnl7.asm
;; gcc -m32 -o exnl7 exnl7.o
;; exnl7 < exnl7file.txt > exnl7.out
;; cat exnl7.out
section .data
prompt db 'Enter a string: ',0
prompt_len equ $ - prompt
BUFSZ equ 1024
STDIN equ 0
STDOUT equ 1
section .bss
buffer resb BUFSZ
section .text
global main
extern read, write
main:
push prompt_len
push prompt
push STDOUT
call write ; terminal or > file
add esp, 12
push BUFSZ - 1 ; leave space for terminating 0
push buffer
push STDIN ; command line or < file
call read
add esp, 12
push eax ; _read returns string length in eax
push buffer
push STDOUT
call write
add esp, 12
mov eax, 0
ret
Execution output:
Enter a string: line 1 of exnl7file.txt
line 2
last line
8. You need to be able to use a number of files combined to
build a program. This may include packages, libraries,
operating system commands, header files, etc.
exnl8f.asm functions source code
; exnl8f.asm example call functions and procedures in another file
extern printf
global jprt
global diff
global ssq
; function definitions, called in exnl8.asm
section .data ; Data section
jprthi: db "Hi from jprt", 10, 0
fmt: db "%s", 10, 0
section .bss ; variables, arrays space
tmpf: resq 1 ; temp space
parf1: resq 1
parf2: resq 1
section .text ; Code section.
jprt: mov rdi,fmt ; no parameters
mov rsi,jprthi
mov rax,0
call printf
ret ; end jprt
diff: mov rax,rdi ; rdi first integer parameter
sub rax,rsi ; rsi second integer parameter
ret ; function result in rax
ssq: movq qword[parf1], xmm0 ; save first parameter
movq qword[parf1], xmm1 ; save second parameter
fld qword[parf1] ; first parameter
fmul qword[parf1] ; squared
fstp qword[tmpf] ; saved
fld qword[parf2] ; second parameter
fmul qword[parf1] ; squared
fadd qword[tmpf] ; sum
fstp qword[tmpf] ; return value
movq xmm2, qword[tmpf] ; return in register
ret
exnl8.asm source code
; exnl8.asm example call funstions and procedures in another file
extern printf
extern jprt ; in exnl8f.asm
extern diff
extern ssq
section .data ; Data section, initialized variables
msg: db "nasm exnl8.asm running", 0 ; C string needs 0
msg2: db "exnl8.asm finished", 0
fmt: db "%s", 10, 0
fmti db "diff = %d", 10, 0
fmtf: db "ssq = %f", 10, 0
af: dq 1.1
bf: dq 3.3
ai: dq 13
bi: dq 27
section .bss ; variable and array section
cf: resq 1
ci: resq 1
tmp: resq 1
section .text ; Code section.
global main
main:
push rbp ; set up stack frame, must be aligned
mov rdi,fmt ; address of format, required register rdi
mov rsi,msg ; address of data
mov rax,0 ; or can be xor rax,rax
call printf ; Call C function
call jprt ; call no parameter procedure
mov rdi,[ai] ; first integer parameter value
mov rsi,[bi] ; second integer paramenter value
call diff ; function return in rax
mov [tmp],rax ; save result and print result using macro
; print
mov rdi, fmti ; address of format string
mov rsi, [tmp] ; int value
mov rax, 0 ; 0 floating point arguments to printf
call printf ; Call C function
movq xmm0, qword[af] ; first double parameter value
movq xmm1, qword[bf] ; second double parameter value
call ssq ; function return in xmm2
movq qword[tmp], xmm2 ; save result and print result
; print
mov rdi, fmtf ; address of format string
movq xmm0, qword[tmp] ; first floating point in fmt
mov rax, 1 ; 1 floating point arguments to printf
call printf ; Call C function
mov rdi,fmt
mov rsi,msg2
mov rax,0
call printf
pop rbp ; restore stack
mov rax,0 ; normal, no error, return value
ret ; return
; function definitions in file exnl8f.asm
Makefile:
exnl8.out : exnl8.asm exnl8f.asm
nasm -f elf64 -l exnl8f.lst exnl8f.asm # must use tabs
nasm -f elf64 -l exnl8.lst exnl8.asm
gcc -m64 -o exnl8 exnl8.o exnl8f.o
exnl8 > exnl8.out
cat exnl8.out
Execution output:
nasm exnl8.asm running
Hi from jprt
diff = -14
ssq = 10.890000
exnl8.asm finished
Last updated 8/12/2019