Skip to content

Commit

Permalink
stack/stack: Add lab exercises, guides and reading
Browse files Browse the repository at this point in the history
Cool description here

Signed-off-by: George Cosma <[email protected]>
  • Loading branch information
george-cosma committed Jun 25, 2024
1 parent 3dfe9fd commit d4be640
Show file tree
Hide file tree
Showing 55 changed files with 1,336 additions and 0 deletions.
13 changes: 13 additions & 0 deletions chapters/stack/intro/drills/tasks/gcd/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# 5. GCD - Greatest Common Divisor

Open `gcd.asm` and run the program.
The code calculates the greatest common divisor (GCD) of two numbers given as parameters using the `eax` and `edx` registers, and then stores the calculated value back in the `eax` register.

1. Make the necessary modifications so that the error message - `Segmentation fault (core dumped)` - no longer appears.
1. Within the `print` label, display the result in the following format:

```c
gcd(49,28)=7
```
If you're having difficulties solving this exercise, go through [this](../../../reading/README.md) reading material
1 change: 1 addition & 0 deletions chapters/stack/intro/drills/tasks/gcd/solution/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
gcd
1 change: 1 addition & 0 deletions chapters/stack/intro/drills/tasks/gcd/solution/Makefile
45 changes: 45 additions & 0 deletions chapters/stack/intro/drills/tasks/gcd/solution/gcd.asm
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
; SPDX-License-Identifier: BSD-3-Clause

%include "../utils/printf32.asm"

section .text

extern printf
global main
main:
; Input values (eax, edx) : the 2 numbers to compute the gcd for.
mov eax, 49
mov edx, 28

push eax
push edx

gcd:
neg eax
je gcd_end

swap_values:
neg eax
push eax
push edx
pop eax
pop edx

subtract_values:
sub eax,edx
jg subtract_values
jne swap_values

gcd_end:
add eax,edx
jne print
inc eax

print:
pop edx
pop ebx

PRINTF32 `gcd(%d, %d) = %d\n\x0`, ebx, edx, eax ; eax = greatest common divisor

xor eax, eax
ret
1 change: 1 addition & 0 deletions chapters/stack/intro/drills/tasks/gcd/support/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
gcd
25 changes: 25 additions & 0 deletions chapters/stack/intro/drills/tasks/gcd/support/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
AS = nasm
CC = gcc
RM = rm

SRCS := $(shell find . -name "*.asm")
OBJS := $(SRCS:.asm=.o)

UTILSDIR := ../utils/

ASFLAGS ?= -f elf32 -F dwarf -I "$(UTILSDIR)"
CFLAGS ?= -Wall
LDFLAGS ?= -m32 -no-pie

TARGET_EXEC = gcd

$(TARGET_EXEC): $(OBJS)
$(CC) $(CFLAGS) $(LDFLAGS) $< -o $@

$(OBJS): $(SRCS)
$(AS) $(ASFLAGS) $< -o $@

.PHONY: clean

clean:
$(RM) -r *.o $(TARGET_EXEC)
44 changes: 44 additions & 0 deletions chapters/stack/intro/drills/tasks/gcd/support/gcd.asm
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
%include "printf32.asm"

section .text

extern printf
global main
main:
; input values (eax, edx): the 2 numbers to compute the gcd for
mov eax, 49
mov edx, 28

push eax
push edx

gcd:
neg eax
je gcd_end

swap_values:
neg eax
push eax
push edx
pop eax
pop edx

subtract_values:
sub eax,edx
jg subtract_values
jne swap_values

gcd_end:
add eax,edx
jne print
inc eax

print:

; TODO 1: solve the 'Segmentation fault!' error

; TODO 2: print the result in the form of: "gdc(eax, edx)=7" with PRINTF32 macro
; output value in eax

xor eax, eax
ret
24 changes: 24 additions & 0 deletions chapters/stack/intro/drills/tasks/gcd/utils/printf32.asm
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
; SPDX-License-Identifier: BSD-3-Clause

;;; macro to use printf with 32bit parameters:
;;; - 1st parameter MUST be an immediate in backquotes `EAX=%d ECX=%x \n\x0`
;;; escape \n and \x0 only work with backquotes
;;; - rest of parameters MUST be 32bit
;;; - gen purpose and flags are preserved
;;; - stack is cleaned
%macro PRINTF32 1-*
pushf
pushad
jmp %%endstr
%%str: db %1
%%endstr:
%rep %0 - 1
%rotate -1
push dword %1
%endrep
push %%str
call printf
add esp, 4*%0
popad
popf
%endmacro
9 changes: 9 additions & 0 deletions chapters/stack/intro/drills/tasks/local-var/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# 4. Local Var

The program `local-var.asm` in the laboratory archive combines two sorted arrays (`array_1` and `array_2`) by placing the resulting array in `array_output` defined in the `.data` section.

Modify the program so that `array_1`, `array_2`, and `array_output` are allocated on the stack.
The array allocation is done using the `sub` instruction.
For the copies of arrays `array_1` and `array_2`, you will need to copy their elements from the `.data` section to the stack before using them.

If you're having difficulties solving this exercise, go through [this](../../../reading/README.md) reading material
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
local-var
106 changes: 106 additions & 0 deletions chapters/stack/intro/drills/tasks/local-var/solution/local-var.asm
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
%include "../utils/printf32.asm"

section .data

%define ARRAY_1_LEN 5
%define ARRAY_2_LEN 7
%define ARRAY_OUTPUT_LEN 12

section .data
array_1 dd 27, 46, 55, 83, 84
array_2 dd 1, 4, 21, 26, 59, 92, 105

section .text

extern printf
global main

main:
mov ebp, esp
sub esp, 4 * ARRAY_1_LEN
mov eax, esp
mov edx, 0
array_1_on_stack:
mov ecx, [array_1 + 4 * edx]
mov [eax], ecx
inc edx
add eax, 4
cmp edx, ARRAY_1_LEN
jl array_1_on_stack
mov eax, esp

sub esp, 4 * ARRAY_2_LEN
mov ebx, esp
mov edx, 0
array_2_on_stack:
mov ecx, [array_2 + 4 * edx]
mov [ebx], ecx
inc edx
add ebx, 4
cmp edx, ARRAY_2_LEN
jl array_2_on_stack
mov ebx, esp
sub esp, 4 * ARRAY_OUTPUT_LEN
mov ecx, esp

merge_arrays:
mov edx, [eax]
cmp edx, [ebx]
jg array_2_lower
array_1_lower:
mov [ecx], edx ; The element from array_1 is lower
add eax, 4
add ecx, 4
jmp verify_array_end
array_2_lower:
mov edx, [ebx]
mov [ecx], edx ; The elements of the array_2 is lower
add ebx, 4
add ecx, 4

verify_array_end:
mov edx, ebp
cmp eax, edx
jge copy_array_2
sub edx, 4 * ARRAY_1_LEN
cmp ebx, ebp
jge copy_array_1
jmp merge_arrays

copy_array_1:
xor edx, edx
mov eax, [eax]
mov [ecx], edx
add ecx, 4
add eax, 4
cmp eax, ebp
jb copy_array_1
jmp print_array
copy_array_2:
xor edx, edx
mov edx, [ebx]
mov [ecx], edx
add ecx, 4
add ebx, 4
mov edx, ebp
sub edx, 4 * ARRAY_1_LEN
cmp ebx, edx
jb copy_array_2

print_array:
PRINTF32 `Array merged:\n\x0`
xor eax, eax
xor ecx, ecx

print:
mov eax, [esp]
PRINTF32 `%d \x0`, eax
add esp, 4
inc ecx
cmp ecx, ARRAY_OUTPUT_LEN
jb print

PRINTF32 `\n\x0`
xor eax, eax
mov esp, ebp
ret
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
local-var
25 changes: 25 additions & 0 deletions chapters/stack/intro/drills/tasks/local-var/support/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
AS = nasm
CC = gcc
RM = rm

SRCS := $(shell find . -name "*.asm")
OBJS := $(SRCS:.asm=.o)

UTILSDIR := ../utils/

ASFLAGS ?= -f elf32 -F dwarf -I "$(UTILSDIR)"
CFLAGS ?= -Wall
LDFLAGS ?= -m32 -no-pie

TARGET_EXEC = local-var

$(TARGET_EXEC): $(OBJS)
$(CC) $(CFLAGS) $(LDFLAGS) $< -o $@

$(OBJS): $(SRCS)
$(AS) $(ASFLAGS) $< -o $@

.PHONY: clean

clean:
$(RM) -r *.o $(TARGET_EXEC)
73 changes: 73 additions & 0 deletions chapters/stack/intro/drills/tasks/local-var/support/local-var.asm
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
%include "printf32.asm"

%define ARRAY_1_LEN 5
%define ARRAY_2_LEN 7
%define ARRAY_OUTPUT_LEN 12

section .data

array_1 dd 27, 46, 55, 83, 84
array_2 dd 1, 4, 21, 26, 59, 92, 105
array_output times 12 dd 0


section .text

extern printf
global main
main:
mov eax, 0 ; counter used for array_1
mov ebx, 0 ; counter used for array_2
mov ecx, 0 ; counter used for the output array

merge_arrays:
mov edx, [array_1 + 4 * eax]
cmp edx, [array_2 + 4 * ebx]
jg array_2_lower
array_1_lower:
mov [array_output + 4 * ecx], edx
inc eax
inc ecx
jmp verify_array_end
array_2_lower:
mov edx, [array_2 + 4 * ebx]
mov [array_output + 4 * ecx], edx
inc ecx
inc ebx

verify_array_end:
cmp eax, ARRAY_1_LEN
jge copy_array_2
cmp ebx, ARRAY_2_LEN
jge copy_array_1
jmp merge_arrays

copy_array_1:
mov edx, [array_1 + 4 * eax]
mov [array_output + 4 * ecx], edx
inc ecx
inc eax
cmp eax, ARRAY_1_LEN
jb copy_array_1
jmp print_array
copy_array_2:
mov edx, [array_2 + 4 * ebx]
mov [array_output + 4 * ecx], edx
inc ecx
inc ebx
cmp ebx, ARRAY_2_LEN
jb copy_array_2

print_array:
PRINTF32 `Array merged:\n\x0`
mov ecx, 0
print:
mov eax, [array_output + 4 * ecx]
PRINTF32 `%d \x0`, eax
inc ecx
cmp ecx, ARRAY_OUTPUT_LEN
jb print

PRINTF32 `\n\x0`
xor eax, eax
ret
Loading

0 comments on commit d4be640

Please sign in to comment.