Skip to content

Commit fc5b69d

Browse files
razvang0307teodutu
authored andcommitted
stack/functions: Add functions lab.
- Add functions lab based off old lab material. - Ignore throwback exercise 0. Signed-off-by: Razvan Miclius <razvang0307@gmail.com>
1 parent 5b707f6 commit fc5b69d

File tree

43 files changed

+1153
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+1153
-0
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
print_reverse_string
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
# Displaying the Reversed String
2+
3+
Navigate to `chapters/stack/functions/drills/tasks/print-rev-string/support/`.
4+
5+
In the file `print_rev_string.asm`, add the `reverse_string()` function so that you have a listing similar to the one below:
6+
7+
```Assembly
8+
[...]
9+
section .text
10+
global main
11+
12+
reverse_string:
13+
push ebp
14+
mov ebp, esp
15+
16+
mov eax, [ebp + 8]
17+
mov ecx, [ebp + 12]
18+
add eax, ecx
19+
dec eax
20+
mov edx, [ebp + 16]
21+
22+
copy_one_byte:
23+
mov bl, [eax]
24+
mov [edx], bl
25+
dec eax
26+
inc edx
27+
loopnz copy_one_byte
28+
29+
inc edx
30+
mov byte [edx], 0
31+
32+
leave
33+
ret
34+
35+
main:
36+
push ebp
37+
mov ebp, esp
38+
[...]
39+
```
40+
41+
> **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.
42+
> The `copy_one_byte` label is part of the `reverse_string()` function.
43+
44+
The `reverse_string()` function reverses a string and has the following signature: `void reverse_string(const char *src, size_t len, char *dst);`.
45+
This means that the first `len` characters of the `src` string are reversed into the `dst` string.
46+
47+
Reverse the `mystring` string into a new string and display that new string.
48+
49+
> **NOTE:** To define a new string, we recommend using the following construction in the data section:
50+
>
51+
> ```Assembly
52+
> store_string times 64 db 0
53+
> ```
54+
>
55+
> This creates a string of 64 zero bytes, enough to store the reverse of the string.
56+
> The equivalent C function call is `reverse_string(mystring, ecx, store_string);`.
57+
> We assume that the length of the string is calculated and stored in the `ecx` register.
58+
>
59+
> You cannot directly use the value of `ecx` in its current form.
60+
> After the `printf()` function call for displaying the length, the value of `ecx` is not preserved.
61+
> To retain it, you have two options:
62+
>
63+
> 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`).
64+
> 1. Store the value of the `ecx` register in a global variable, which you define in the `.data` section.
65+
>
66+
> 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.
67+
68+
If you're having trouble solving this exercise, go through [this](../../../reading/functions.md) reading material.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../support/Makefile
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
section .data
2+
mystring db "This is my string", 0
3+
print_format db "String length is %d", 10, 0
4+
store_string times 64 db 0
5+
6+
section .text
7+
8+
extern printf
9+
extern puts
10+
global main
11+
12+
reverse_string:
13+
push ebp
14+
mov ebp, esp
15+
16+
mov eax, [ebp + 8] ; get the address of the string
17+
mov ecx, [ebp + 12] ; get the length of the string
18+
add eax, ecx ; point to the last character
19+
dec eax
20+
mov edx, [ebp + 16] ; get the address of the buffer
21+
22+
copy_one_byte:
23+
mov bl, [eax]
24+
mov [edx], bl ; transfer one byte from the end of the source string to the beginning of the destination
25+
dec eax
26+
inc edx
27+
loopnz copy_one_byte
28+
29+
inc edx
30+
mov byte [edx], 0
31+
32+
leave
33+
ret
34+
35+
main:
36+
push ebp
37+
mov ebp, esp
38+
39+
mov eax, mystring
40+
xor ecx, ecx
41+
test_one_byte:
42+
mov bl, [eax]
43+
test bl, bl
44+
jz out
45+
inc eax
46+
inc ecx
47+
jmp test_one_byte
48+
49+
out:
50+
; save ecx's value since it can be changed by printf
51+
push ecx
52+
53+
push ecx
54+
push print_format
55+
call printf
56+
add esp, 8
57+
58+
pop ecx
59+
60+
push store_string
61+
push ecx
62+
push mystring
63+
call reverse_string
64+
add esp, 12
65+
66+
push store_string
67+
call puts
68+
add esp, 4
69+
70+
leave
71+
ret
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
print_reverse_string
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
AS = nasm
2+
CC = gcc
3+
4+
SRCS := $(shell find . -name "*.asm")
5+
OBJS := $(SRCS:.asm=.o)
6+
7+
UTILSDIR := ../utils/
8+
9+
ASFLAGS ?= -f elf32 -F dwarf -I "$(UTILSDIR)"
10+
CFLAGS ?= -Wall
11+
LDFLAGS ?= -m32 -no-pie
12+
13+
all: print_reverse_string
14+
15+
print_reverse_string_: print_reverse_string.o
16+
17+
%.o: %.asm
18+
$(AS) $(ASFLAGS) $< -o $@
19+
20+
.PHONY: clean
21+
22+
clean:
23+
-rm -f *.o print_reverse_string
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
%include "../utils/printf32.asm"
2+
3+
section .data
4+
mystring db "This is my string", 0
5+
fmt_str db "[before]: %s\n[after]: ", 0
6+
7+
section .text
8+
9+
extern puts
10+
extern printf
11+
global main
12+
13+
main:
14+
push ebp
15+
mov ebp, esp
16+
17+
mov eax, mystring
18+
xor ecx, ecx
19+
test_one_byte:
20+
mov bl, [eax]
21+
test bl, bl
22+
je out
23+
inc eax
24+
inc ecx
25+
jmp test_one_byte
26+
27+
out:
28+
push mystring
29+
push fmt_str
30+
call printf
31+
add esp, 8
32+
33+
; TODO: print reverse string
34+
35+
leave
36+
ret
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
; SPDX-License-Identifier: BSD-3-Clause
2+
3+
;;; macro to use printf with 32bit parameters:
4+
;;; - 1st parameter MUST be an immediate in backquotes `EAX=%d ECX=%x \n\x0`
5+
;;; escape \n and \x0 only work with backquotes
6+
;;; - rest of parameters MUST be 32bit
7+
;;; - gen purpose and flags are preserved
8+
;;; - stack is cleaned
9+
%macro PRINTF32 1-*
10+
pushf
11+
pushad
12+
jmp %%endstr
13+
%%str: db %1
14+
%%endstr:
15+
%rep %0 - 1
16+
%rotate -1
17+
push dword %1
18+
%endrep
19+
push %%str
20+
call printf
21+
add esp, 4*%0
22+
popad
23+
popf
24+
%endmacro
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
rot13
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# Bonus: Rot13
2+
3+
Navigate to `chapters/stack/functions/drills/tasks/rot13/support/`.
4+
5+
Create and use a function that performs [rot13](https://rot13.com/) translation of a string.
6+
7+
## Bonus: Rot13++
8+
9+
Implement `rot13` on an array of strings: the strings are contiguous in memory separated by the string terminator (`NULL`-byte, `0`).
10+
For example, `lorem\0ipsum\0dolor\0` is an array of three strings.
11+
12+
Apply `rot13` to alphabetical characters and replace the string terminator with a space (`' '`, blank, character `32`, or `0x20`).
13+
Thus, the initial string `lorem\0ipsum\0dolor\0` will translate to `yberz vcfhz qbybe`.
14+
15+
> **NOTE:** To define the array of strings containing the string terminator, use a construction like:
16+
>
17+
> ```Assembly
18+
> mystring db "lorem", 0, "ipsum", 0, "dolor", 0
19+
> ```
20+
>
21+
> **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:
22+
>
23+
> ```Assembly
24+
> len dd 10
25+
> ```
26+
>
27+
> 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.
28+
29+
If you're having trouble solving this exercise, go through [this](../../../reading/functions.md) reading material.

0 commit comments

Comments
 (0)