Skip to content

Commit

Permalink
stack/functions: Add functions lab.
Browse files Browse the repository at this point in the history
- Add functions lab based off old lab material.
- Ignore throwback exercise 0.

Signed-off-by: Razvan Miclius <[email protected]>
  • Loading branch information
razvang0307 authored and teodutu committed Jan 7, 2025
1 parent 5b707f6 commit fc5b69d
Show file tree
Hide file tree
Showing 43 changed files with 1,153 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
print_reverse_string
68 changes: 68 additions & 0 deletions chapters/stack/functions/drills/tasks/print-rev-string/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# Displaying the Reversed String

Navigate to `chapters/stack/functions/drills/tasks/print-rev-string/support/`.

In the file `print_rev_string.asm`, add the `reverse_string()` function so that you have a listing similar to the one below:

```Assembly
[...]
section .text
global main
reverse_string:
push ebp
mov ebp, esp
mov eax, [ebp + 8]
mov ecx, [ebp + 12]
add eax, ecx
dec eax
mov edx, [ebp + 16]
copy_one_byte:
mov bl, [eax]
mov [edx], bl
dec eax
inc edx
loopnz copy_one_byte
inc edx
mov byte [edx], 0
leave
ret
main:
push ebp
mov ebp, esp
[...]
```

> **IMPORTANT:** When copying the `reverse_string()` function into your program, remember that the function starts at the `reverse_string()` label and ends at the `main` label.
> The `copy_one_byte` label is part of the `reverse_string()` function.
The `reverse_string()` function reverses a string and has the following signature: `void reverse_string(const char *src, size_t len, char *dst);`.
This means that the first `len` characters of the `src` string are reversed into the `dst` string.

Reverse the `mystring` string into a new string and display that new string.

> **NOTE:** To define a new string, we recommend using the following construction in the data section:
>
> ```Assembly
> store_string times 64 db 0
> ```
>
> This creates a string of 64 zero bytes, enough to store the reverse of the string.
> The equivalent C function call is `reverse_string(mystring, ecx, store_string);`.
> We assume that the length of the string is calculated and stored in the `ecx` register.
>
> You cannot directly use the value of `ecx` in its current form.
> After the `printf()` function call for displaying the length, the value of `ecx` is not preserved.
> To retain it, you have two options:
>
> 1. Store the value of the `ecx` register on the stack beforehand (using `push ecx` before the `printf` call) and then restore it after the `printf` call (using `pop ecx`).
> 1. Store the value of the `ecx` register in a global variable, which you define in the `.data` section.
>
> You cannot use another register because there is a high chance that even that register will be modified by the `printf` call to display the length of the string.
If you're having trouble solving this exercise, go through [this](../../../reading/functions.md) reading material.
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
section .data
mystring db "This is my string", 0
print_format db "String length is %d", 10, 0
store_string times 64 db 0

section .text

extern printf
extern puts
global main

reverse_string:
push ebp
mov ebp, esp

mov eax, [ebp + 8] ; get the address of the string
mov ecx, [ebp + 12] ; get the length of the string
add eax, ecx ; point to the last character
dec eax
mov edx, [ebp + 16] ; get the address of the buffer

copy_one_byte:
mov bl, [eax]
mov [edx], bl ; transfer one byte from the end of the source string to the beginning of the destination
dec eax
inc edx
loopnz copy_one_byte

inc edx
mov byte [edx], 0

leave
ret

main:
push ebp
mov ebp, esp

mov eax, mystring
xor ecx, ecx
test_one_byte:
mov bl, [eax]
test bl, bl
jz out
inc eax
inc ecx
jmp test_one_byte

out:
; save ecx's value since it can be changed by printf
push ecx

push ecx
push print_format
call printf
add esp, 8

pop ecx

push store_string
push ecx
push mystring
call reverse_string
add esp, 12

push store_string
call puts
add esp, 4

leave
ret
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
print_reverse_string
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
AS = nasm
CC = gcc

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

UTILSDIR := ../utils/

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

all: print_reverse_string

print_reverse_string_: print_reverse_string.o

%.o: %.asm
$(AS) $(ASFLAGS) $< -o $@

.PHONY: clean

clean:
-rm -f *.o print_reverse_string
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
%include "../utils/printf32.asm"

section .data
mystring db "This is my string", 0
fmt_str db "[before]: %s\n[after]: ", 0

section .text

extern puts
extern printf
global main

main:
push ebp
mov ebp, esp

mov eax, mystring
xor ecx, ecx
test_one_byte:
mov bl, [eax]
test bl, bl
je out
inc eax
inc ecx
jmp test_one_byte

out:
push mystring
push fmt_str
call printf
add esp, 8

; TODO: print reverse string

leave
ret
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
1 change: 1 addition & 0 deletions chapters/stack/functions/drills/tasks/rot13/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
rot13
29 changes: 29 additions & 0 deletions chapters/stack/functions/drills/tasks/rot13/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Bonus: Rot13

Navigate to `chapters/stack/functions/drills/tasks/rot13/support/`.

Create and use a function that performs [rot13](https://rot13.com/) translation of a string.

## Bonus: Rot13++

Implement `rot13` on an array of strings: the strings are contiguous in memory separated by the string terminator (`NULL`-byte, `0`).
For example, `lorem\0ipsum\0dolor\0` is an array of three strings.

Apply `rot13` to alphabetical characters and replace the string terminator with a space (`' '`, blank, character `32`, or `0x20`).
Thus, the initial string `lorem\0ipsum\0dolor\0` will translate to `yberz vcfhz qbybe`.

> **NOTE:** To define the array of strings containing the string terminator, use a construction like:
>
> ```Assembly
> mystring db "lorem", 0, "ipsum", 0, "dolor", 0
> ```
>
> **NOTE:** You will need to know when to stop traversing the array of strings. The simplest way is to define a length variable in the `.data` section, like so:
>
> ```Assembly
> len dd 10
> ```
>
> where you either store the total length of the string (from the beginning to the last `NULL` byte) or the number of strings in the array.
If you're having trouble solving this exercise, go through [this](../../../reading/functions.md) reading material.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
print_string_len
26 changes: 26 additions & 0 deletions chapters/stack/functions/drills/tasks/string-print-len/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Displaying the Length of a String

Navigate to `chapters/stack/functions/drills/tasks/string-print-len/support/`.

The program `print_string_len.asm` displays the length of a string using the `PRINTF32` macro.
The calculation of the length of the `mystring` string occurs within the program (it is already implemented).

Implement the program to display the length of the string using the `printf` function.

At the end, you will have the length of the string displayed twice: initially with the `PRINTF32` macro and then with the external function call `printf`.

> **NOTE:** Consider that the `printf` call is of the form `printf("String length is %u\n", len);`.
> You need to construct the stack for this call.
>
> The steps to follow are:
>
> 1. Mark the symbol `printf` as external.
> 1. Define the format string `"String length is %u", 10, 0`.
> 1. Make the function call to `printf`, i.e.:
> 1. Put the two arguments on the stack: the format string and the length.
> 1. Call `printf` using `call`.
> 1. Restore the stack.
>
> The length of the string is found in the `ecx` register.
If you're having trouble solving this exercise, go through [this](../../../reading/functions.md) reading material.
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
%include "../utils/printf32.asm"

section .data
mystring db "This is my string", 0
print_format db "String length is %d", 10, 0

section .text

extern printf
global main

main:
push ebp
mov ebp, esp

mov eax, mystring
xor ecx, ecx
test_one_byte:
mov bl, byte [eax]
test bl, bl
jz out
inc eax
inc ecx
jmp test_one_byte

out:
PRINTF32 `[PRINTF32]: %d\n[printf]: \x0`, ecx

push ecx
push print_format
call printf
add esp, 8

leave
ret
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
AS = nasm
CC = gcc

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

UTILSDIR := ../utils/

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

all: print_string_length

print_string_length: print_string_length.o

%.o: %.asm
$(AS) $(ASFLAGS) $< -o $@

.PHONY: clean

clean:
rm -f *.o print_string_length
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
%include "../utils/printf32.asm"

section .data
mystring db "This is my string", 0

section .text

extern puts
extern printf
global main

main:
push ebp
mov ebp, esp

mov eax, mystring
xor ecx, ecx
test_one_byte:
mov bl, byte [eax]
test bl, bl
je out
inc eax
inc ecx
jmp test_one_byte

out:
PRINTF32 `[PRINTF32]: %d\n[printf]: \x0`, ecx

; TODO: print string length using printf

leave
ret
Loading

0 comments on commit fc5b69d

Please sign in to comment.