Outputing text using interrupts

boot.asm

[ORG 0x7c00]
 
jmp main
 
msg   db 'The itsy bitsy spider climbed up the waterspout. Down came the rain and washed the spider out. Out came the sun and dried up all the rain and the itsy bitsy spider climbed up the spout again.',0x0

; reference
; http://en.wikipedia.org/wiki/INT_10H
main:
    mov     ah, 0xe			; 0xe is used for teletype output
    mov     edx, 0			; edx is our string offset
    ch_loop:
    mov     al, [msg + edx] ; copy character into al from string offset
    int     0x10			; call interrupt 0x10 to output character
    inc     edx				; increment edx (move to next character)
    test    al, al			; test for 0
    jnz     ch_loop			; if not 0, go to ch_loop
     
    hlt
     
    times 510-($-$$) db 0
    db 0x55
    db 0xAA

nasm -f bin -o boot.img boot.asm

Output text using video memory

boot.asm

[ORG 0x7c00]
 
jmp main
 
msg   db 'The itsy bitsy spider climbed up the waterspout. Down came the rain and washed the spider out. Out came the sun and dried up all the rain and the itsy bitsy spider climbed up the spout again.',0x0
 
main:
    mov     ax, 0xb800			; 0xb800 is starting address to Color Video Memory
    mov     es, ax				; copy 0xb800 to es register
    mov     di, 0				; set di to 0
    
	; Now we have [es:di] => 0xb800:0x0
    mov     bx, 0				; bx is going to be our string offset
    loop:
	; must be aligned as the following
	; byte 1: character
	; byte 2: the color of character
    movzx   cx, byte[msg + bx]	; copy character from msg plus offset into cx
								; NOTE: must specify to copy a byte
    mov     ax, cx				; copy into character (in cx) into ax
    stosb						; copies at AL into [ES:DI]
    mov     ax, 5				; 5 is the color Magenta
    stosb						; copies at AL into [ES:DI]
    inc     bx					; increment bx (move to next character)
    test    cx, cx				; test for 0
    jnz     loop				; if not zero, go to loop
	
    hlt
	
    times 510-($-$$) db 0
    db 0x55
    db 0xAA

nasm -f bin -o boot.img boot.asm

Calling assembly code in C

power.asm

global power

section .text
	power:
	; initialize eax to 1
	mov		eax, 1
	; esp+8 is the exponent
	mov		ebx, [esp+8]
	loop:
	; esp+4 is the base
	imul	eax, [esp+4]
	dec		ebx
	cmp		ebx, 0
	jnz		loop
	ret

math.c

#include <stdio.h>

int power(int a, int b);

int main()
{
	int p = power(32,3);
	printf("%i\n", p);
}

https://github.com/randcode-generator/assembly_and_c

To compile and run:
nasm -f elf power.asm && gcc math.c power.o -o math && ./math

Arrays in assembly

global main
 
extern printf
 
section .data
	array:			db 0xF204, 0x64
	array2:			dw 0x1260, 0x62
	array3:			dw 0x54, 0x32
	arraydb:		db 10, 33, 88, 99
	arraydw:		dw 77, 460, 120, 550
	fmtStr: 		db '%i',0xA,0

section .text
	main:

	; Read a byte from array
	; Note: 0xF204 is truncated to
	; 0x04 because array is declared
	; as byte (db)
	movzx	edx, byte[array]
	call 	printout

	; Read a word from array
	; Note: it will be interpreted as 0x6404
	; because it's stored backwards
	movzx	edx, word[array]
	call 	printout

	; Read a word from array2
	movzx	edx, word[array2]
	call 	printout

	; Read a word from array2
	; with 1 byte offset
	; Note: it will be interpreted as 0x6212
	movzx	edx, word[array2+1]
	call 	printout

	; Read a word from array3
	; with 1 byte offset
	; Note: it will be interpreted as 0x3200
	movzx	edx, word[array3+1]
	call 	printout

	; Loop through byte by byte arraydb
	mov 	ebx, 0
	loop:
	movzx	edx, byte[arraydb+ebx]
	call 	printout
	inc 	ebx
	cmp		ebx, 4
	jne		loop

	; Loop through word by word arraydb
	mov 	ebx, 0
	loop2:
	; Size of word is 2 byte, increment
	; by 2
	movzx	edx, word[arraydw+(ebx*2)]
	call 	printout
	inc 	ebx
	cmp		ebx, 4
	jne		loop2

	ret

	printout:
	; print out the argument
    sub     esp, 4
    mov     [esp], edx          ; Copy edx into address of esp
    ; Load the format string into the stack
    sub     esp, 4              ; Allocate space on the stack for one 4 byte parameter
    lea     eax, [fmtStr]       ; Load string into eax
    mov     [esp], eax          ; Copy eax into the address of esp
 
    ; Call printf
    call    printf              ; Call printf(3):
                     
	add     esp, 8				; pop stack by 8 (2 elements * 4 bytes each element)
	ret

https://github.com/randcode-generator/array-in-assembly

To compile and run:
nasm -f elf32 array.asm && gcc -o array array.o && ./array

Branch in assembly

global main
 
extern printf
 
section .data
	strEqual: 		db 'edx is equal to 10',0xA,0
	strNotEqual: 	db 'edx is not equal to 10',0xA,0
	fmtStr: 		db 'Argument: %i',0xA,0

section .text
	main:
	
	push 10
	call isValueEqualTo10
	add esp, 4
	
	push 11
	call isValueEqualTo10
	add esp, 4
	ret
	
	isValueEqualTo10:
	push ebp					; save ebp into stack
	mov ebp, esp				; copy esp into ebp

	mov		edx, [ebp+8]		; Copy the first argument into edx
	
	; print out the argument
	sub		esp, 4
	mov		[esp], edx			; Copy edx into address of esp
	; Load the format string into the stack
	sub     esp, 4          	; Allocate space on the stack for one 4 byte parameter
	lea     eax, [fmtStr]		; Load string into eax
	mov     [esp], eax      	; Copy eax into the address of esp

	; Call printf
	call    printf          	; Call printf(3):
								; int printf(const char *format, ...);						
	add		esp, 8

	; compare
	mov		edx, [ebp+8]		; Copy the first argument into edx
	cmp		edx, 10				; Is edx equal to 10?
	jne		else				; Go to else label if edx is not equal to 10

	; Load the format string into the stack
	sub     esp, 4          	; Allocate space on the stack for one 4 byte parameter
	lea     eax, [strEqual]		; Load string into eax
	mov     [esp], eax      	; Copy eax into the address of esp

	; Call printf
	call    printf          	; Call printf(3):
								; int printf(const char *format, ...);
	jmp endBranch
	
	else:
	
	; Load the format string into the stack
	sub     esp, 4          	; Allocate space on the stack for one 4 byte parameter
	lea     eax, [strNotEqual]	; Load string into eax
	mov     [esp], eax      	; Copy eax into the address of esp

	; Call printf
	call    printf          ; Call printf(3):
							; int printf(const char *format, ...);
	endBranch:
	add		esp, 4
	pop ebp
	ret

https://github.com/randcode-generator/branch-in-assembly

To compile and run:
nasm -f elf32 branch.asm && gcc -o branch branch.o && ./branch

Loops in assembly

global main
 
extern printf
 
section .data
	fmtStr: db '%i',0xA,0

section .text
	main:
	
	mov		edx, 10			; Copy 10 to edx
	looping:
	push	edx				; Save edx by pushing into stack
	
	; Load the first argument into the stack
	sub     esp, 4			; Allocate space on the stack for one 4 byte parameter
	mov     [esp], edx		; Copy eax into the address of esp

	; Load the format string into the stack
	sub     esp, 4          ; Allocate space on the stack for one 4 byte parameter
	lea     eax, [fmtStr]	; Load string into eax
	mov     [esp], eax      ; Copy eax into the address of esp

	; Call printf
	call    printf          ; Call printf(3):
							; int printf(const char *format, ...);

	; Return the stack (pointer) to it's original position (0 elements)
	add     esp, 8			; Pop the stack (There were 2 "sub esp,4")
	
	pop		edx				; Pop the stack and assign value to edx
	dec		edx				; Decrement edx by 1
	cmp		edx, 0			; Is edx equal to 0? zf is set if edx is 0
	jnz		looping			; if flag does not have zf set, go to "looping"
	ret

https://github.com/randcode-generator/loops-in-assembly

To compile and run:
nasm -f elf loop.asm && gcc -o loop loop.o && ./loop

Function call assembly

global main

extern printf

section .data
    fmtStr: db '%i',0xA,0
    
section .text
    main:
    push 5				; argment 4
	push 10				; argment 3
	push 20				; argment 2
	push 50				; argment 1
	call calculate		; call the function "calculate"
						; eax has the return value of calculate function
	add esp, 16			; pop stack by 16. (4 arguments * 4 bytes each argument)
	
	push eax			; store the return value in stack
	lea eax, [fmtStr]	; load the formatted string into eax
	push eax			; store formatted string into eax
	call printf			; call the printf function
	add esp, 8			; pop stack by 8 (2 elements * 4 bytes each element)
	ret					; return function
	
	calculate:
	; formula: arg1 * arg2 + arg3 * arg4
	push ebp			; save ebp into stack
	mov ebp, esp		; copy esp into ebp
	sub esp, 4			; move stack pointer by 4 (1 local variable)
	mov eax, [ebp+8]	; copy argument 1 (50) into eax
	imul eax, [ebp+12]	; multiply eax with argument 2 (20) to eax
	mov [ebp-4], eax	; copy the eax value (20 * 50 = 1000) into local variable (ebp-4)
	
	mov eax, [ebp+16]	; copy argument 3 (10) into eax
	imul eax, [ebp+20]	; multiply eax with argument 4 (10 * 5 = 50) to eax
	
	add eax, [ebp-4]	; add eax with local variable (ebp-4)
	
	mov esp, ebp		; copy ebp to esp. All local variables are popped
	pop ebp				; copy the top of the stack to ebp, restore the original ebp value
	ret					; return function

https://github.com/randcode-generator/function-call-assembly.git

To compile and run:
nasm -f elf function.asm && gcc -o function function.o && ./function

Output in assembly

; http://docs.cs.up.ac.za/programming/asm/derick_tut/syscalls.html

global _start

section .data
	message:     db 'Printout', 0xA
	messageLen:  equ $-message

section .text
_start:
	; Call write(2) syscall:
	;       ssize_t write(int fd, const void *buf, size_t count)
	mov eax, 4				; Syscall, sys_write: 
	mov ebx, 1				; fd: 1 is for stdout
	mov ecx, message		; buf: address of string
	mov edx, messageLen		; count: string length
	int 0x80				; interrupt
	
	; Call exit(2) syscall:
	;       void exit(int status)
	mov eax, 1				; Syscall, sys_exit
	mov ebx, 0				; status: exit status 0
	int 0x80

https://github.com/randcode-generator/output-in-assembly

To compile and run:
nasm -f elf output.asm && ld output.o && ./a.out

Calling printf in assembly using nasm

global main
 
extern printf
 
section .data
	fmtStr: db 'printf: a1 - %i, a2 - %s',0xA,0
	param1: db 'Parameter String'
 
section .text
	main:

	; Load the second argument into the stack
	sub     esp, 4			; Allocate space on the stack for one 4 byte parameter
	lea     eax, [param1]   ; Load string into eax
	mov     [esp], eax		; Copy eax into the address of esp
	
	; Load the first argument into the stack
	sub     esp, 4			; Allocate space on the stack for one 4 byte parameter
	mov     eax, 8			; Copy 8 into eax
	add     eax, 1098		; eax = eax + 1098
	mov     [esp], eax		; Copy eax into the address of esp

	; Load the format string into the stack
	sub     esp, 4          ; Allocate space on the stack for one 4 byte parameter
	lea     eax, [fmtStr]	; Load string into eax
	mov     [esp], eax      ; Copy eax into the address of esp

	; Call printf
	call    printf          ; Call printf(3):
							; int printf(const char *format, ...);

	; Return the stack (pointer) to it's original position (0 elements)
	add     esp, 12         ; Pop the stack (There were 3 "sub esp,4")

	ret

https://github.com/randcode-generator/printf-in-assembly

To compile and run:
nasm -f elf32 printf.asm && gcc -o printf printf.o && ./printf