diff --git a/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/README.md b/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/README.md new file mode 100644 index 00000000..32c8fe3f --- /dev/null +++ b/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/README.md @@ -0,0 +1,8 @@ +# Repair Export Problems + +Navigate to `drills/tasks/export-fix/support/`. + +Each subdirectory (`support/a-func/`, `suppoer/b-var/`, `support/c-var-2/`) contains a problem related to exporting some symbols (functions or variables). +In each subdirectory, run the `make` command, identify the problem and edit the files needed to fix the problem. + +If you're having difficulties solving this exercise, go through [this relevant section](../../../reading/memory-layout-c-asm.md) reading material. \ No newline at end of file diff --git a/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/solution/a-func/.gitignore b/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/solution/a-func/.gitignore new file mode 100644 index 00000000..95811e00 --- /dev/null +++ b/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/solution/a-func/.gitignore @@ -0,0 +1 @@ +/main diff --git a/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/solution/a-func/Makefile b/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/solution/a-func/Makefile new file mode 120000 index 00000000..9da39e10 --- /dev/null +++ b/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/solution/a-func/Makefile @@ -0,0 +1 @@ +../../support/a-func/Makefile \ No newline at end of file diff --git a/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/solution/a-func/hidden.c b/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/solution/a-func/hidden.c new file mode 100644 index 00000000..7d978b4d --- /dev/null +++ b/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/solution/a-func/hidden.c @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: BSD-3-Clause + +int hidden_value; + +void init(void) +{ + hidden_value = 0; +} + +void set(int value) +{ + hidden_value = value; +} + +int get(void) +{ + return hidden_value; +} diff --git a/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/solution/a-func/main.c b/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/solution/a-func/main.c new file mode 100644 index 00000000..ac72986f --- /dev/null +++ b/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/solution/a-func/main.c @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#include +#include "ops.h" + +int main(void) +{ + set(10); + printf("get(): %d\n", get()); + + age = 33; + print_age(); + + return 0; +} diff --git a/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/solution/a-func/ops.h b/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/solution/a-func/ops.h new file mode 100644 index 00000000..22d3d3ac --- /dev/null +++ b/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/solution/a-func/ops.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ + +#ifndef OPS_H_ +#define OPS_H_ 1 + +void init(void); +void set(int value); +int get(void); + +extern int age; +void print_age(void); + +#endif diff --git a/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/solution/a-func/plain.c b/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/solution/a-func/plain.c new file mode 100644 index 00000000..b620ed57 --- /dev/null +++ b/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/solution/a-func/plain.c @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#include + +int age; + +void print_age(void) +{ + printf("age: %d\n", age); +} diff --git a/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/solution/b-var/.gitignore b/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/solution/b-var/.gitignore new file mode 100644 index 00000000..95811e00 --- /dev/null +++ b/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/solution/b-var/.gitignore @@ -0,0 +1 @@ +/main diff --git a/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/solution/b-var/Makefile b/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/solution/b-var/Makefile new file mode 120000 index 00000000..32ae761d --- /dev/null +++ b/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/solution/b-var/Makefile @@ -0,0 +1 @@ +../../support/b-var/Makefile \ No newline at end of file diff --git a/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/solution/b-var/hidden.c b/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/solution/b-var/hidden.c new file mode 100644 index 00000000..a1e11369 --- /dev/null +++ b/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/solution/b-var/hidden.c @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: BSD-3-Clause + +static int hidden_value; + +void init(void) +{ + hidden_value = 0; +} + +void set(int value) +{ + hidden_value = value; +} + +int get(void) +{ + return hidden_value; +} diff --git a/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/solution/b-var/main.c b/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/solution/b-var/main.c new file mode 100644 index 00000000..ac72986f --- /dev/null +++ b/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/solution/b-var/main.c @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#include +#include "ops.h" + +int main(void) +{ + set(10); + printf("get(): %d\n", get()); + + age = 33; + print_age(); + + return 0; +} diff --git a/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/solution/b-var/ops.h b/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/solution/b-var/ops.h new file mode 100644 index 00000000..22d3d3ac --- /dev/null +++ b/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/solution/b-var/ops.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ + +#ifndef OPS_H_ +#define OPS_H_ 1 + +void init(void); +void set(int value); +int get(void); + +extern int age; +void print_age(void); + +#endif diff --git a/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/solution/b-var/plain.c b/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/solution/b-var/plain.c new file mode 100644 index 00000000..b620ed57 --- /dev/null +++ b/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/solution/b-var/plain.c @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#include + +int age; + +void print_age(void) +{ + printf("age: %d\n", age); +} diff --git a/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/solution/c-var-2/.gitignore b/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/solution/c-var-2/.gitignore new file mode 100644 index 00000000..95811e00 --- /dev/null +++ b/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/solution/c-var-2/.gitignore @@ -0,0 +1 @@ +/main diff --git a/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/solution/c-var-2/Makefile b/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/solution/c-var-2/Makefile new file mode 120000 index 00000000..0f2e757a --- /dev/null +++ b/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/solution/c-var-2/Makefile @@ -0,0 +1 @@ +../../support/c-var-2/Makefile \ No newline at end of file diff --git a/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/solution/c-var-2/hidden.c b/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/solution/c-var-2/hidden.c new file mode 100644 index 00000000..a1e11369 --- /dev/null +++ b/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/solution/c-var-2/hidden.c @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: BSD-3-Clause + +static int hidden_value; + +void init(void) +{ + hidden_value = 0; +} + +void set(int value) +{ + hidden_value = value; +} + +int get(void) +{ + return hidden_value; +} diff --git a/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/solution/c-var-2/main.c b/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/solution/c-var-2/main.c new file mode 100644 index 00000000..ac72986f --- /dev/null +++ b/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/solution/c-var-2/main.c @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#include +#include "ops.h" + +int main(void) +{ + set(10); + printf("get(): %d\n", get()); + + age = 33; + print_age(); + + return 0; +} diff --git a/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/solution/c-var-2/ops.h b/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/solution/c-var-2/ops.h new file mode 100644 index 00000000..9be0fbb2 --- /dev/null +++ b/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/solution/c-var-2/ops.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ + +#ifndef OPS_H_ +#define OPS_H_ 1 + +void init(void); +void set(int value); +int get(void); +extern int age; +void print_age(void); + +#endif diff --git a/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/solution/c-var-2/plain.c b/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/solution/c-var-2/plain.c new file mode 100644 index 00000000..b620ed57 --- /dev/null +++ b/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/solution/c-var-2/plain.c @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#include + +int age; + +void print_age(void) +{ + printf("age: %d\n", age); +} diff --git a/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/support/a-func/.gitignore b/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/support/a-func/.gitignore new file mode 100644 index 00000000..95811e00 --- /dev/null +++ b/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/support/a-func/.gitignore @@ -0,0 +1 @@ +/main diff --git a/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/support/a-func/Makefile b/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/support/a-func/Makefile new file mode 100644 index 00000000..4d3893ca --- /dev/null +++ b/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/support/a-func/Makefile @@ -0,0 +1,21 @@ +CFLAGS = -Wall -g +CXXFLAGS = -Wall -g + +.DEFAULT_GOAL: all + +.PHONY: all clean + +all: main + +main: main.o hidden.o plain.o + $(CC) $(LDFLAGS) -o $@ $^ + +main.o: main.c ops.h + +hidden.o: hidden.c + +plain.o: plain.c + +clean: + -rm -f main *.o + -rm -f *~ diff --git a/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/support/a-func/hidden.c b/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/support/a-func/hidden.c new file mode 100644 index 00000000..a864c611 --- /dev/null +++ b/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/support/a-func/hidden.c @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: BSD-3-Clause + +int hidden_value; + +void init(void) +{ + hidden_value = 0; +} + +static void set(int value) +{ + hidden_value = value; +} + +int get(void) +{ + return hidden_value; +} diff --git a/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/support/a-func/main.c b/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/support/a-func/main.c new file mode 100644 index 00000000..ac72986f --- /dev/null +++ b/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/support/a-func/main.c @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#include +#include "ops.h" + +int main(void) +{ + set(10); + printf("get(): %d\n", get()); + + age = 33; + print_age(); + + return 0; +} diff --git a/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/support/a-func/ops.h b/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/support/a-func/ops.h new file mode 100644 index 00000000..22d3d3ac --- /dev/null +++ b/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/support/a-func/ops.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ + +#ifndef OPS_H_ +#define OPS_H_ 1 + +void init(void); +void set(int value); +int get(void); + +extern int age; +void print_age(void); + +#endif diff --git a/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/support/a-func/plain.c b/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/support/a-func/plain.c new file mode 100644 index 00000000..b620ed57 --- /dev/null +++ b/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/support/a-func/plain.c @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#include + +int age; + +void print_age(void) +{ + printf("age: %d\n", age); +} diff --git a/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/support/b-var/.gitignore b/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/support/b-var/.gitignore new file mode 100644 index 00000000..95811e00 --- /dev/null +++ b/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/support/b-var/.gitignore @@ -0,0 +1 @@ +/main diff --git a/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/support/b-var/Makefile b/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/support/b-var/Makefile new file mode 100644 index 00000000..4d3893ca --- /dev/null +++ b/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/support/b-var/Makefile @@ -0,0 +1,21 @@ +CFLAGS = -Wall -g +CXXFLAGS = -Wall -g + +.DEFAULT_GOAL: all + +.PHONY: all clean + +all: main + +main: main.o hidden.o plain.o + $(CC) $(LDFLAGS) -o $@ $^ + +main.o: main.c ops.h + +hidden.o: hidden.c + +plain.o: plain.c + +clean: + -rm -f main *.o + -rm -f *~ diff --git a/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/support/b-var/hidden.c b/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/support/b-var/hidden.c new file mode 100644 index 00000000..a1e11369 --- /dev/null +++ b/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/support/b-var/hidden.c @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: BSD-3-Clause + +static int hidden_value; + +void init(void) +{ + hidden_value = 0; +} + +void set(int value) +{ + hidden_value = value; +} + +int get(void) +{ + return hidden_value; +} diff --git a/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/support/b-var/main.c b/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/support/b-var/main.c new file mode 100644 index 00000000..ac72986f --- /dev/null +++ b/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/support/b-var/main.c @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#include +#include "ops.h" + +int main(void) +{ + set(10); + printf("get(): %d\n", get()); + + age = 33; + print_age(); + + return 0; +} diff --git a/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/support/b-var/ops.h b/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/support/b-var/ops.h new file mode 100644 index 00000000..22d3d3ac --- /dev/null +++ b/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/support/b-var/ops.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ + +#ifndef OPS_H_ +#define OPS_H_ 1 + +void init(void); +void set(int value); +int get(void); + +extern int age; +void print_age(void); + +#endif diff --git a/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/support/b-var/plain.c b/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/support/b-var/plain.c new file mode 100644 index 00000000..ce5252a4 --- /dev/null +++ b/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/support/b-var/plain.c @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#include + +static int age; + +void print_age(void) +{ + printf("age: %d\n", age); +} diff --git a/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/support/c-var-2/.gitignore b/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/support/c-var-2/.gitignore new file mode 100644 index 00000000..95811e00 --- /dev/null +++ b/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/support/c-var-2/.gitignore @@ -0,0 +1 @@ +/main diff --git a/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/support/c-var-2/Makefile b/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/support/c-var-2/Makefile new file mode 100644 index 00000000..4d3893ca --- /dev/null +++ b/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/support/c-var-2/Makefile @@ -0,0 +1,21 @@ +CFLAGS = -Wall -g +CXXFLAGS = -Wall -g + +.DEFAULT_GOAL: all + +.PHONY: all clean + +all: main + +main: main.o hidden.o plain.o + $(CC) $(LDFLAGS) -o $@ $^ + +main.o: main.c ops.h + +hidden.o: hidden.c + +plain.o: plain.c + +clean: + -rm -f main *.o + -rm -f *~ diff --git a/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/support/c-var-2/hidden.c b/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/support/c-var-2/hidden.c new file mode 100644 index 00000000..56b13cc7 --- /dev/null +++ b/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/support/c-var-2/hidden.c @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: BSD-3-Clause + +extern int hidden_value; + +void init(void) +{ + hidden_value = 0; +} + +void set(int value) +{ + hidden_value = value; +} + +int get(void) +{ + return hidden_value; +} diff --git a/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/support/c-var-2/main.c b/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/support/c-var-2/main.c new file mode 100644 index 00000000..ac72986f --- /dev/null +++ b/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/support/c-var-2/main.c @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#include +#include "ops.h" + +int main(void) +{ + set(10); + printf("get(): %d\n", get()); + + age = 33; + print_age(); + + return 0; +} diff --git a/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/support/c-var-2/ops.h b/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/support/c-var-2/ops.h new file mode 100644 index 00000000..e484a8b4 --- /dev/null +++ b/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/support/c-var-2/ops.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ + +#ifndef OPS_H_ +#define OPS_H_ 1 + +void init(void); +void set(int value); +int get(void); +void print_age(void); + +#endif diff --git a/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/support/c-var-2/plain.c b/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/support/c-var-2/plain.c new file mode 100644 index 00000000..ce5252a4 --- /dev/null +++ b/chapters/memory-layout/c-assembly-interaction/drills/tasks/export-fix/support/c-var-2/plain.c @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#include + +static int age; + +void print_age(void) +{ + printf("age: %d\n", age); +} diff --git a/chapters/memory-layout/c-assembly-interaction/drills/tasks/include-fix/README.md b/chapters/memory-layout/c-assembly-interaction/drills/tasks/include-fix/README.md new file mode 100644 index 00000000..50d4469e --- /dev/null +++ b/chapters/memory-layout/c-assembly-interaction/drills/tasks/include-fix/README.md @@ -0,0 +1,12 @@ +# Warning (No Error) + +Navigate to `drills/tasks/include-fix/support`. + +Run the `make` command. +You will get a warning. +Is it from compiling or linking? +Resolve this warning by editing the `support/hello.c` file. + +Resolve the warning without using the `#include` directive. + +If you're having difficulties solving this exercise, go through [this relevant section](../../../reading/memoy-layout-c-asm.md) reading material. diff --git a/chapters/memory-layout/c-assembly-interaction/drills/tasks/include-fix/solution/Makefile b/chapters/memory-layout/c-assembly-interaction/drills/tasks/include-fix/solution/Makefile new file mode 100644 index 00000000..3e07b939 --- /dev/null +++ b/chapters/memory-layout/c-assembly-interaction/drills/tasks/include-fix/solution/Makefile @@ -0,0 +1,17 @@ +CFLAGS = -Wall -g +CXXFLAGS = -Wall -g + +.DEFAULT_GOAL: all + +.PHONY: all clean + +all: hello + +hello: hello.o + $(CC) $(LDFLAGS) -o $@ $^ + +hello.o: hello.c + +clean: + -rm -f hello + -rm -f *~ diff --git a/chapters/memory-layout/c-assembly-interaction/drills/tasks/include-fix/solution/hello.c b/chapters/memory-layout/c-assembly-interaction/drills/tasks/include-fix/solution/hello.c new file mode 100644 index 00000000..6f8870b9 --- /dev/null +++ b/chapters/memory-layout/c-assembly-interaction/drills/tasks/include-fix/solution/hello.c @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: BSD-3-Clause + +extern int puts(const char *str); + +static void hi(void) +{ + puts("Hi!"); +} + +static void bye(void) +{ + puts("Bye!"); +} + +int main(void) +{ + hi(); + bye(); +} diff --git a/chapters/memory-layout/c-assembly-interaction/drills/tasks/include-fix/support/.gitignore b/chapters/memory-layout/c-assembly-interaction/drills/tasks/include-fix/support/.gitignore new file mode 100644 index 00000000..e92569d0 --- /dev/null +++ b/chapters/memory-layout/c-assembly-interaction/drills/tasks/include-fix/support/.gitignore @@ -0,0 +1 @@ +/hello diff --git a/chapters/memory-layout/c-assembly-interaction/drills/tasks/include-fix/support/Makefile b/chapters/memory-layout/c-assembly-interaction/drills/tasks/include-fix/support/Makefile new file mode 100644 index 00000000..3e07b939 --- /dev/null +++ b/chapters/memory-layout/c-assembly-interaction/drills/tasks/include-fix/support/Makefile @@ -0,0 +1,17 @@ +CFLAGS = -Wall -g +CXXFLAGS = -Wall -g + +.DEFAULT_GOAL: all + +.PHONY: all clean + +all: hello + +hello: hello.o + $(CC) $(LDFLAGS) -o $@ $^ + +hello.o: hello.c + +clean: + -rm -f hello + -rm -f *~ diff --git a/chapters/memory-layout/c-assembly-interaction/drills/tasks/include-fix/support/hello.c b/chapters/memory-layout/c-assembly-interaction/drills/tasks/include-fix/support/hello.c new file mode 100644 index 00000000..ef112487 --- /dev/null +++ b/chapters/memory-layout/c-assembly-interaction/drills/tasks/include-fix/support/hello.c @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: BSD-3-Clause + +static void hi(void) +{ + puts("Hi!"); +} + +static void bye(void) +{ + puts("Bye!"); +} + +int main(void) +{ + hi(); + bye(); +} diff --git a/chapters/memory-layout/c-assembly-interaction/drills/tasks/regs-preserve/README.md b/chapters/memory-layout/c-assembly-interaction/drills/tasks/regs-preserve/README.md new file mode 100644 index 00000000..b79d9fb6 --- /dev/null +++ b/chapters/memory-layout/c-assembly-interaction/drills/tasks/regs-preserve/README.md @@ -0,0 +1,25 @@ +# Keeping Records + +Navigate to `drills/tasks/regs-preserve/support` and open `main.asm` + +In this subdirectory of the lab's task repository you will find the `print_reverse_array()` function implemented by a simple loop that makes repeated calls of the `printf()` function. + +Follow the code in the `main.asm` file, compile and run the program. +What happened? +The program runs indefinitely. +This is because the `printf()` function does not preserve the value in the `ecx` register, used here as a counter. + +Uncomment the lines marked `TODO1` and rerun the program. + +## Troubleshooting SEGFAULT + +Decompose the lines marked `TODO2` in the assembly file from the previous exercise. +The code sequence makes a call to the `double_array()` function, implemented in C, just before displaying the vector using the function seen earlier. + +Compile and run the program. +To debug the segfault you can use the `objdump` utility to trace the assembly language code corresponding to the `double_array()` function. +Notice which of the registers used before and after the call are modified by this function. + +Add the instructions for preserving and restoring the required registers to the assembly file. + +If you're having difficulties solving this exercise, go through [this relevant section](../../../reading/memory-layout-c-asm.md) reading material. diff --git a/chapters/memory-layout/c-assembly-interaction/drills/tasks/regs-preserve/solution/Makefile b/chapters/memory-layout/c-assembly-interaction/drills/tasks/regs-preserve/solution/Makefile new file mode 100644 index 00000000..7caf95b4 --- /dev/null +++ b/chapters/memory-layout/c-assembly-interaction/drills/tasks/regs-preserve/solution/Makefile @@ -0,0 +1,21 @@ +CFLAGS = -Wall -g -m32 +ASM = nasm +ASMFLAGS = -f elf32 + +.DEFAULT_GOAL: all + +.PHONY: all clean + +all: main + +main: main.o double_array.o + $(CC) $(LDFLAGS) -m32 -o $@ $^ + +main.o: main.asm + $(ASM) $(ASMFLAGS) -o $@ $< + +double_array.o: double_array.c + $(CC) $(CFLAGS) -c -o $@ $< + +clean: + -rm -f main *.o diff --git a/chapters/memory-layout/c-assembly-interaction/drills/tasks/regs-preserve/solution/double_array.c b/chapters/memory-layout/c-assembly-interaction/drills/tasks/regs-preserve/solution/double_array.c new file mode 100644 index 00000000..06200604 --- /dev/null +++ b/chapters/memory-layout/c-assembly-interaction/drills/tasks/regs-preserve/solution/double_array.c @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#include + +void double_array(unsigned int *array, unsigned int len) +{ + size_t i; + + for (i = 0; i < len; i++) + *(array + i) *= 2; +} diff --git a/chapters/memory-layout/c-assembly-interaction/drills/tasks/regs-preserve/solution/main.asm b/chapters/memory-layout/c-assembly-interaction/drills/tasks/regs-preserve/solution/main.asm new file mode 100644 index 00000000..aca1596a --- /dev/null +++ b/chapters/memory-layout/c-assembly-interaction/drills/tasks/regs-preserve/solution/main.asm @@ -0,0 +1,75 @@ +; SPDX-License-Identifier: BSD-3-Clause + +extern printf +extern double_array + +section .data + myarray dd 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 + myarray_len dd 10 + + format_string db "%d ", 0 + newline db 13, 10, 0 + + +section .text + + +print_reverse_array: + push ebp + mov ebp, esp + + ; save ebx in callee + push ebx + + ; [ebp+8] is array pointer + ; [ebp+12] is array length + mov ebx, [ebp+8] + mov ecx, [ebp+12] + xor eax, eax + +next: + +; TODO1: Decomentați următoarele două linii comentate + push ecx + push dword [ebx+ecx*4-4] + push format_string + call printf + add esp, 8 + pop ecx + loop next + + push newline + call printf + add esp, 4 + + pop ebx + + leave + ret + + +global main + +main: + push ebp + mov ebp, esp + + mov edx, [myarray_len] + lea eax, [myarray] + +; TODO2: Decomentați această secvență de cod + push edx + push eax + call double_array + add esp, 8 + + mov edx, [myarray_len] + lea eax, [myarray] + push edx + push eax + call print_reverse_array + add esp, 8 + + + leave + ret diff --git a/chapters/memory-layout/c-assembly-interaction/drills/tasks/regs-preserve/support/.gitignore b/chapters/memory-layout/c-assembly-interaction/drills/tasks/regs-preserve/support/.gitignore new file mode 100644 index 00000000..95811e00 --- /dev/null +++ b/chapters/memory-layout/c-assembly-interaction/drills/tasks/regs-preserve/support/.gitignore @@ -0,0 +1 @@ +/main diff --git a/chapters/memory-layout/c-assembly-interaction/drills/tasks/regs-preserve/support/Makefile b/chapters/memory-layout/c-assembly-interaction/drills/tasks/regs-preserve/support/Makefile new file mode 100644 index 00000000..7caf95b4 --- /dev/null +++ b/chapters/memory-layout/c-assembly-interaction/drills/tasks/regs-preserve/support/Makefile @@ -0,0 +1,21 @@ +CFLAGS = -Wall -g -m32 +ASM = nasm +ASMFLAGS = -f elf32 + +.DEFAULT_GOAL: all + +.PHONY: all clean + +all: main + +main: main.o double_array.o + $(CC) $(LDFLAGS) -m32 -o $@ $^ + +main.o: main.asm + $(ASM) $(ASMFLAGS) -o $@ $< + +double_array.o: double_array.c + $(CC) $(CFLAGS) -c -o $@ $< + +clean: + -rm -f main *.o diff --git a/chapters/memory-layout/c-assembly-interaction/drills/tasks/regs-preserve/support/double_array.c b/chapters/memory-layout/c-assembly-interaction/drills/tasks/regs-preserve/support/double_array.c new file mode 100644 index 00000000..06200604 --- /dev/null +++ b/chapters/memory-layout/c-assembly-interaction/drills/tasks/regs-preserve/support/double_array.c @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#include + +void double_array(unsigned int *array, unsigned int len) +{ + size_t i; + + for (i = 0; i < len; i++) + *(array + i) *= 2; +} diff --git a/chapters/memory-layout/c-assembly-interaction/drills/tasks/regs-preserve/support/main.asm b/chapters/memory-layout/c-assembly-interaction/drills/tasks/regs-preserve/support/main.asm new file mode 100644 index 00000000..2dc7c342 --- /dev/null +++ b/chapters/memory-layout/c-assembly-interaction/drills/tasks/regs-preserve/support/main.asm @@ -0,0 +1,73 @@ +; SPDX-License-Identifier: BSD-3-Clause + +extern printf +extern double_array + +section .data + myarray dd 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 + myarray_len dd 10 + + format_string db "%d ", 0 + newline db 13, 10, 0 + + +section .text + + +print_reverse_array: + push ebp + mov ebp, esp + + ; save ebx in callee + push ebx + + ; [ebp+8] is array pointer + ; [ebp+12] is array length + mov ebx, [ebp+8] + mov ecx, [ebp+12] + xor eax, eax + +next: + +; TODO1: Decomentați următoarele două linii comentate +; push ecx + push dword [ebx+ecx*4-4] + push format_string + call printf + add esp, 8 +; pop ecx + loop next + + push newline + call printf + add esp, 4 + + pop ebx + + leave + ret + + +global main + +main: + push ebp + mov ebp, esp + + mov edx, [myarray_len] + lea eax, [myarray] + +; TODO2: Decomentați această secvență de cod +; push edx +; push eax +; call double_array +; add esp, 8 + + push edx + push eax + call print_reverse_array + add esp, 8 + + + leave + ret diff --git a/chapters/memory-layout/c-assembly-interaction/reading/memory-layout-c-asm.md b/chapters/memory-layout/c-assembly-interaction/reading/memory-layout-c-asm.md new file mode 100644 index 00000000..3601ed01 --- /dev/null +++ b/chapters/memory-layout/c-assembly-interaction/reading/memory-layout-c-asm.md @@ -0,0 +1,52 @@ +# C - Assembly Interaction: Memory Perspective + +Considering that assembly language poses challenges both in reading and in developing code, the general trend is to migrate towards high-level languages (which are much easier to read and provide a more user-friendly API). +However, there are still situations where, for optimization reasons, small assembly routines are used and integrated into the high-level language module. + +In this laboratory, we will explore how assembly modules can be integrated into C programs and vice versa. + +## Using Assembly Procedures in C Functions + +Using assembly procedures in C functions for a C program to be executed, it must be translated into the machine code of the processor; +this is the task of a compiler. +Since this compiled code is not always optimal, in some cases it is preferable to replace portions of code written in C with portions of assembly code that do the same thing, but with better performance. + +### Declaration of the Procedure + +In order to ensure that the assembly procedure and Module C are properly combined and compatible, the following steps must be followed: + +- declare the procedure label as global, using the GLOBAL directive. +In addition to this, any data that will be used by the procedure must be declared as global. + +- using the EXTERN directive to declare procedures and global data as external. + +## Calling C Functions from Assembly Procedures + +In most cases, calling routines or functions from the standard C library in an assembly language program is a much more complex operation than vice versa. +Take the example of calling the `printf()` function from an assembly language program: + +```Assembly +global main + +external printf + +section .data + +text db "291 is the best!", 10, 0 +strformat db "%s", 0 + +section .code + +main: + push dword text + push dword strformat + call printf + add esp, 8 + ret +``` + +Note that the procedure is declared as global and is called `main` - the starting point of any C program. +Since in C the parameters are stacked in reverse order, the string offset is set first, followed by the format string offset. +The C function can be called afterwards, but the stack must be restored when the function exits. + +When linking assembly code the standard C library (or the library containing the functions you use) must be included. diff --git a/chapters/stack/c-assembly-interaction/drills/tasks/max-assembly-calls-x64/README.md b/chapters/stack/c-assembly-interaction/drills/tasks/max-assembly-calls-x64/README.md new file mode 100644 index 00000000..a5b75497 --- /dev/null +++ b/chapters/stack/c-assembly-interaction/drills/tasks/max-assembly-calls-x64/README.md @@ -0,0 +1,5 @@ +# Bonus: Maximum Calculation in C with Call from Assembly - 64 Bits + +Enter the directory `drills/tasks/max-assembly-calls-x64/support` and implement the maximum calculation in C with a call from Assembly language on a 64-bit system. +Start from the program used in `drills/tasks/max-assembly-calls`, ensuring it runs on a 64-bit system. +Follow the instructions from the previous exercise and pay attention to the order of parameters. diff --git a/chapters/stack/c-assembly-interaction/drills/tasks/max-assembly-calls-x64/support/.gitignore b/chapters/stack/c-assembly-interaction/drills/tasks/max-assembly-calls-x64/support/.gitignore new file mode 100644 index 00000000..ba2906d0 --- /dev/null +++ b/chapters/stack/c-assembly-interaction/drills/tasks/max-assembly-calls-x64/support/.gitignore @@ -0,0 +1 @@ +main diff --git a/chapters/stack/c-assembly-interaction/drills/tasks/max-assembly-calls-x64/support/Makefile b/chapters/stack/c-assembly-interaction/drills/tasks/max-assembly-calls-x64/support/Makefile new file mode 100644 index 00000000..b7964fd0 --- /dev/null +++ b/chapters/stack/c-assembly-interaction/drills/tasks/max-assembly-calls-x64/support/Makefile @@ -0,0 +1,21 @@ +CFLAGS = -Wall -g +ASM = nasm +ASMFLAGS = -f elf64 + +.DEFAULT_GOAL: all + +.PHONY: all clean + +all: main + +main: main.o max.o + $(CC) $(LDFLAGS) -o $@ $^ + +main.o: main.asm + $(ASM) $(ASMFLAGS) -o $@ $< + +max.o: max.c + $(CC) $(CFLAGS) -c -o $@ $< + +clean: + -rm -f main *.o diff --git a/chapters/stack/c-assembly-interaction/drills/tasks/max-assembly-calls-x64/support/main.asm b/chapters/stack/c-assembly-interaction/drills/tasks/max-assembly-calls-x64/support/main.asm new file mode 100644 index 00000000..fb13e9a9 --- /dev/null +++ b/chapters/stack/c-assembly-interaction/drills/tasks/max-assembly-calls-x64/support/main.asm @@ -0,0 +1,39 @@ +; SPDX-License-Identifier: BSD-3-Clause + +BITS 64 +extern printf +extern get_max + +section .data + arr: dd 19, 7, 129, 87, 54, 218, 67, 12, 19, 99 + len: equ $-arr + + print_format: db "max: %u", 13, 10, 0 + +section .text + +global main + +main: + push rbp + mov rbp, rsp + + ; Compute length in eax. + ; Divide by 4 (we are using integer data type of 4 bytes) by + ; using shr 2 (shift right with 2 bits). + mov eax, len + shr eax, 2 + + push rax + push arr + call get_max + add esp, 8 + + ; Print max. + push rax + push print_format + call printf + add esp, 8 + + leave + ret diff --git a/chapters/stack/c-assembly-interaction/drills/tasks/max-assembly-calls-x64/support/max.c b/chapters/stack/c-assembly-interaction/drills/tasks/max-assembly-calls-x64/support/max.c new file mode 100644 index 00000000..2643968f --- /dev/null +++ b/chapters/stack/c-assembly-interaction/drills/tasks/max-assembly-calls-x64/support/max.c @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#include + +unsigned int get_max(unsigned int *arr, unsigned int len) +{ + unsigned int max = 0; + size_t i; + + for (i = 0; i < len; i++) + if (max < arr[i]) + max = arr[i]; + + return max; +} diff --git a/chapters/stack/c-assembly-interaction/drills/tasks/max-assembly-calls/.gitignore b/chapters/stack/c-assembly-interaction/drills/tasks/max-assembly-calls/.gitignore new file mode 100644 index 00000000..1a94556d --- /dev/null +++ b/chapters/stack/c-assembly-interaction/drills/tasks/max-assembly-calls/.gitignore @@ -0,0 +1,2 @@ +main + diff --git a/chapters/stack/c-assembly-interaction/drills/tasks/max-assembly-calls/README.md b/chapters/stack/c-assembly-interaction/drills/tasks/max-assembly-calls/README.md new file mode 100644 index 00000000..db1ddb16 --- /dev/null +++ b/chapters/stack/c-assembly-interaction/drills/tasks/max-assembly-calls/README.md @@ -0,0 +1,33 @@ +# Maximum Calculation in C with Call from Assembly + +Navigate to `drills/tasks/max-assembly-calls/support/` and open `main.asm` + +In this directory you can find an implementation of calculating the maximum of a number where the `main()` function is defined in assembly language from which the `get_max()` function defined in C is called. + +Trace the code in the two files and how the function arguments and return value are passed. + +Compile and run the program. + +> **IMPORTANT:** +> Pay attention to understanding the code before proceeding to the next exercise. + +## Extending Maximum Computation in C with Call from Assembly + +Extend the program from the previous exercise (in assembly language and C) so that the `get_max()` function now has the signature `unsigned int get_max(unsigned int *arr, unsigned int len, unsigned int *pos)`. +The third argument to the function is the address where the position in the vector on which the maximum is found will be held. + +The position in the vector on which the maximum is found will also be displayed on display. + +> **TIP:** +> To hold the position, it is best to define a global variable in the assembly file (`main.asm`) in the `.data` section, of the form +> +> ```Assembly +> pos: dd 0 +> ``` +> +> This variable you will pass (by address) to the `get_max()` call and by value to the `printf()` call for display. +> +> For display modify the `print_format` string and the `printf()` call in the assembly file (`main.asm`) to allow two values to be displayed: maximum and position. +> + +If you're having difficulties solving this exercise, go through [this relevant section](../../../reading/stack-c-asm.md) reading material. diff --git a/chapters/stack/c-assembly-interaction/drills/tasks/max-assembly-calls/solution/max-assembly-calls-2/.gitignore b/chapters/stack/c-assembly-interaction/drills/tasks/max-assembly-calls/solution/max-assembly-calls-2/.gitignore new file mode 100644 index 00000000..ba2906d0 --- /dev/null +++ b/chapters/stack/c-assembly-interaction/drills/tasks/max-assembly-calls/solution/max-assembly-calls-2/.gitignore @@ -0,0 +1 @@ +main diff --git a/chapters/stack/c-assembly-interaction/drills/tasks/max-assembly-calls/solution/max-assembly-calls-2/Makefile b/chapters/stack/c-assembly-interaction/drills/tasks/max-assembly-calls/solution/max-assembly-calls-2/Makefile new file mode 100644 index 00000000..70a84d50 --- /dev/null +++ b/chapters/stack/c-assembly-interaction/drills/tasks/max-assembly-calls/solution/max-assembly-calls-2/Makefile @@ -0,0 +1,22 @@ +ASFLAGS := -f elf64 +LDFLAGS := -no-pie +CFLAGS := -g -Wall -Wextra -Werror -fno-pic -masm=intel +ASM = nasm + +.DEFAULT_GOAL: all + +.PHONY: all clean + +all: main + +main: main.o max.o + $(CC) $(LDFLAGS) -o $@ $^ + +main.o: main.asm + $(ASM) $(ASMFLAGS) -o $@ $< + +max.o: max.c + $(CC) $(CFLAGS) -c -o $@ $< + +clean: + -rm -f main *.o diff --git a/chapters/stack/c-assembly-interaction/drills/tasks/max-assembly-calls/solution/max-assembly-calls-2/main.asm b/chapters/stack/c-assembly-interaction/drills/tasks/max-assembly-calls/solution/max-assembly-calls-2/main.asm new file mode 100644 index 00000000..4c9c003e --- /dev/null +++ b/chapters/stack/c-assembly-interaction/drills/tasks/max-assembly-calls/solution/max-assembly-calls-2/main.asm @@ -0,0 +1,43 @@ +; SPDX-License-Identifier: BSD-3-Clause + +BITS 64 +extern printf +extern get_max + +section .data + arr: dd 19, 7, 129, 87, 54, 218, 67, 12, 19, 99 + len: equ $-arr + pos: dd 0 + + print_format: db "max: %u on position: %u", 13, 10, 0 + +section .text + +global main + +main: + push rbp + mov rbp, rsp + + ; Compute length in eax. + ; Divide by 4 (we are using integer data type of 4 bytes) by + ; using shr 2 (shift right with 2 bits). + xor rax, rax + mov eax, len + shr eax, 2 + + mov rdi, arr + xor rsi, rsi + mov esi, eax + mov rdx, pos + call get_max + + ; Print max. + mov rdi, print_format + xor rsi, rsi + mov esi, eax + mov rdx, [pos] + call printf + + leave + ret diff --git a/chapters/stack/c-assembly-interaction/drills/tasks/max-assembly-calls/solution/max-assembly-calls-2/max.c b/chapters/stack/c-assembly-interaction/drills/tasks/max-assembly-calls/solution/max-assembly-calls-2/max.c new file mode 100644 index 00000000..222739c1 --- /dev/null +++ b/chapters/stack/c-assembly-interaction/drills/tasks/max-assembly-calls/solution/max-assembly-calls-2/max.c @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#include + +unsigned int get_max(unsigned int *arr, unsigned int len, unsigned int *pos) +{ + unsigned int max = 0; + size_t i; + + for (i = 0; i < len; i++) + if (max < arr[i]) { + max = arr[i]; + *pos = i; + } + + return max; +} diff --git a/chapters/stack/c-assembly-interaction/drills/tasks/max-assembly-calls/solution/max-assembly-calls/.gitignore b/chapters/stack/c-assembly-interaction/drills/tasks/max-assembly-calls/solution/max-assembly-calls/.gitignore new file mode 100644 index 00000000..ba2906d0 --- /dev/null +++ b/chapters/stack/c-assembly-interaction/drills/tasks/max-assembly-calls/solution/max-assembly-calls/.gitignore @@ -0,0 +1 @@ +main diff --git a/chapters/stack/c-assembly-interaction/drills/tasks/max-assembly-calls/solution/max-assembly-calls/Makefile b/chapters/stack/c-assembly-interaction/drills/tasks/max-assembly-calls/solution/max-assembly-calls/Makefile new file mode 100644 index 00000000..bf004873 --- /dev/null +++ b/chapters/stack/c-assembly-interaction/drills/tasks/max-assembly-calls/solution/max-assembly-calls/Makefile @@ -0,0 +1,21 @@ +CFLAGS = -Wall -g -m32 +ASM = nasm +ASMFLAGS = -f elf32 + +.DEFAULT_GOAL: all + +.PHONY: all clean + +all: main + +main: main.o max.o + $(CC) $(LDFLAGS) -m32 -o $@ $^ + +main.o: main.asm + $(ASM) $(ASMFLAGS) -o $@ $< + +max.o: max.c + $(CC) $(CFLAGS) -c -o $@ $< + +clean: + -rm -f main *.o diff --git a/chapters/stack/c-assembly-interaction/drills/tasks/max-assembly-calls/solution/max-assembly-calls/main.asm b/chapters/stack/c-assembly-interaction/drills/tasks/max-assembly-calls/solution/max-assembly-calls/main.asm new file mode 100644 index 00000000..f81f1cd7 --- /dev/null +++ b/chapters/stack/c-assembly-interaction/drills/tasks/max-assembly-calls/solution/max-assembly-calls/main.asm @@ -0,0 +1,41 @@ +; SPDX-License-Identifier: BSD-3-Clause + +extern printf +extern get_max + +section .data + arr: dd 19, 7, 129, 87, 54, 218, 67, 12, 19, 99 + len: equ $-arr + pos: dd 0 + + print_format: db "max: %u on position: %u", 13, 10, 0 + +section .text + +global main + +main: + push ebp + mov ebp, esp + + ; Compute length in eax. + ; Divide by 4 (we are using integer data type of 4 bytes) by + ; using shr 2 (shift right with 2 bits). + mov eax, len + shr eax, 2 + + push pos + push eax + push arr + call get_max + add esp, 12 + + ; Print max. + push dword [pos] + push eax + push print_format + call printf + add esp, 12 + + leave + ret diff --git a/chapters/stack/c-assembly-interaction/drills/tasks/max-assembly-calls/solution/max-assembly-calls/max.c b/chapters/stack/c-assembly-interaction/drills/tasks/max-assembly-calls/solution/max-assembly-calls/max.c new file mode 100644 index 00000000..549d68f9 --- /dev/null +++ b/chapters/stack/c-assembly-interaction/drills/tasks/max-assembly-calls/solution/max-assembly-calls/max.c @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#include + +unsigned int get_max(unsigned int *arr, unsigned int len, unsigned int *pos) +{ + unsigned int max = 0; + size_t i; + + for (i = 0; i < len; i++) + if (max < arr[i]) { + max = arr[i]; + *pos = i; + } + return max; +} diff --git a/chapters/stack/c-assembly-interaction/drills/tasks/max-assembly-calls/support/.gitignore b/chapters/stack/c-assembly-interaction/drills/tasks/max-assembly-calls/support/.gitignore new file mode 100644 index 00000000..95811e00 --- /dev/null +++ b/chapters/stack/c-assembly-interaction/drills/tasks/max-assembly-calls/support/.gitignore @@ -0,0 +1 @@ +/main diff --git a/chapters/stack/c-assembly-interaction/drills/tasks/max-assembly-calls/support/Makefile b/chapters/stack/c-assembly-interaction/drills/tasks/max-assembly-calls/support/Makefile new file mode 100644 index 00000000..bf004873 --- /dev/null +++ b/chapters/stack/c-assembly-interaction/drills/tasks/max-assembly-calls/support/Makefile @@ -0,0 +1,21 @@ +CFLAGS = -Wall -g -m32 +ASM = nasm +ASMFLAGS = -f elf32 + +.DEFAULT_GOAL: all + +.PHONY: all clean + +all: main + +main: main.o max.o + $(CC) $(LDFLAGS) -m32 -o $@ $^ + +main.o: main.asm + $(ASM) $(ASMFLAGS) -o $@ $< + +max.o: max.c + $(CC) $(CFLAGS) -c -o $@ $< + +clean: + -rm -f main *.o diff --git a/chapters/stack/c-assembly-interaction/drills/tasks/max-assembly-calls/support/main.asm b/chapters/stack/c-assembly-interaction/drills/tasks/max-assembly-calls/support/main.asm new file mode 100644 index 00000000..06eeff4b --- /dev/null +++ b/chapters/stack/c-assembly-interaction/drills/tasks/max-assembly-calls/support/main.asm @@ -0,0 +1,38 @@ +; SPDX-License-Identifier: BSD-3-Clause + +extern printf +extern get_max + +section .data + arr: dd 19, 7, 129, 87, 54, 218, 67, 12, 19, 99 + len: equ $-arr + + print_format: db "max: %u", 13, 10, 0 + +section .text + +global main + +main: + push ebp + mov ebp, esp + + ; Compute length in eax. + ; Divide by 4 (we are using integer data type of 4 bytes) by + ; using shr 2 (shift right with 2 bits). + mov eax, len + shr eax, 2 + + push eax + push arr + call get_max + add esp, 8 + + ; Print max. + push eax + push print_format + call printf + add esp, 8 + + leave + ret diff --git a/chapters/stack/c-assembly-interaction/drills/tasks/max-assembly-calls/support/max.c b/chapters/stack/c-assembly-interaction/drills/tasks/max-assembly-calls/support/max.c new file mode 100644 index 00000000..2643968f --- /dev/null +++ b/chapters/stack/c-assembly-interaction/drills/tasks/max-assembly-calls/support/max.c @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#include + +unsigned int get_max(unsigned int *arr, unsigned int len) +{ + unsigned int max = 0; + size_t i; + + for (i = 0; i < len; i++) + if (max < arr[i]) + max = arr[i]; + + return max; +} diff --git a/chapters/stack/c-assembly-interaction/drills/tasks/max-c-calls-x64/README.md b/chapters/stack/c-assembly-interaction/drills/tasks/max-c-calls-x64/README.md new file mode 100644 index 00000000..43d96aec --- /dev/null +++ b/chapters/stack/c-assembly-interaction/drills/tasks/max-c-calls-x64/README.md @@ -0,0 +1,19 @@ +# Maximum Computation in Assembly with 64-bit C Call + +Navigate to `drills/tasks/max-c-calls-x64/support` and open `main.c` + +In this subdirectory you should have implemented the maximum assembly language calculation on a 64-bit system. +Start the program from exercises 4 and 5 in such a way that you run it using a 64-bit system. + +> **TIP:** +> . +> +> The first thing to note is that on the x64 architecture the registers are 8 bytes in size and have different names than the 32-bit ones (in addition to extending the traditional ones: `eax` register becomes `rax`, `ebx` register becomes `rbx`, etc., there are new ones: R10-R15: for more information see [here]()). +> +> Also, on x64 architecture parameters are no longer sent to the stack, but put in registers. +> The first 3 parameters are put in: `rdi`, `rsi` and `rdx` registers. +> This is not a uniformly adopted convention. +> This convention is only valid on Linux, on Windows there are other registers which are used to pass the parameters of a function. +> The calling convention requires that, for functions with a variable number of arguments, `rax` register be set to the number of vector registers used to pass arguments. +> `printf()` is a variable argument count function, and unless you use registers other than those mentioned in the previous paragraph for passing arguments, you must set `rax = 0` before calling. +> Read more [here](). diff --git a/chapters/stack/c-assembly-interaction/drills/tasks/max-c-calls-x64/solution/.gitignore b/chapters/stack/c-assembly-interaction/drills/tasks/max-c-calls-x64/solution/.gitignore new file mode 100644 index 00000000..35911aba --- /dev/null +++ b/chapters/stack/c-assembly-interaction/drills/tasks/max-c-calls-x64/solution/.gitignore @@ -0,0 +1 @@ +mainmax diff --git a/chapters/stack/c-assembly-interaction/drills/tasks/max-c-calls-x64/solution/Makefile b/chapters/stack/c-assembly-interaction/drills/tasks/max-c-calls-x64/solution/Makefile new file mode 120000 index 00000000..a39be4f2 --- /dev/null +++ b/chapters/stack/c-assembly-interaction/drills/tasks/max-c-calls-x64/solution/Makefile @@ -0,0 +1 @@ +../support/Makefile \ No newline at end of file diff --git a/chapters/stack/c-assembly-interaction/drills/tasks/max-c-calls-x64/solution/main.c b/chapters/stack/c-assembly-interaction/drills/tasks/max-c-calls-x64/solution/main.c new file mode 100644 index 00000000..789368c4 --- /dev/null +++ b/chapters/stack/c-assembly-interaction/drills/tasks/max-c-calls-x64/solution/main.c @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#include + +unsigned int get_max(unsigned int *arr, unsigned int len); + +int main(void) +{ + unsigned int arr[] = { 19, 7, 129, 87, 54, 218, 67, 12, 19, 99 }; + unsigned int max; + + max = get_max(arr, 10); + + printf("max: %u\n", max); + + return 0; +} diff --git a/chapters/stack/c-assembly-interaction/drills/tasks/max-c-calls-x64/solution/max.asm b/chapters/stack/c-assembly-interaction/drills/tasks/max-c-calls-x64/solution/max.asm new file mode 100644 index 00000000..1197eac0 --- /dev/null +++ b/chapters/stack/c-assembly-interaction/drills/tasks/max-c-calls-x64/solution/max.asm @@ -0,0 +1,32 @@ +; SPDX-License-Identifier: BSD-3-Clause + +BITS 64 +section .text + +global get_max + +get_max: + push rbp + mov rbp, rsp + + push rbx ; the callee should save ebx if it uses it + + mov rbx, rdi ; first argument + mov rcx, rsi ; second argument + ; third argument is in rdx + + xor rax, rax + +compare: + cmp eax, [rbx+rcx*4-4] + jge check_end + mov r12, rcx ; array starts at zero: use fancy 64-bit arch register + dec r12 + mov [rdx], r12 ; save position + mov eax, [rbx+rcx*4-4] +check_end: + loopnz compare + + pop rbx ; the callee should restore ebx before returning + leave + ret diff --git a/chapters/stack/c-assembly-interaction/drills/tasks/max-c-calls-x64/support/.gitignore b/chapters/stack/c-assembly-interaction/drills/tasks/max-c-calls-x64/support/.gitignore new file mode 100644 index 00000000..35911aba --- /dev/null +++ b/chapters/stack/c-assembly-interaction/drills/tasks/max-c-calls-x64/support/.gitignore @@ -0,0 +1 @@ +mainmax diff --git a/chapters/stack/c-assembly-interaction/drills/tasks/max-c-calls-x64/support/Makefile b/chapters/stack/c-assembly-interaction/drills/tasks/max-c-calls-x64/support/Makefile new file mode 100644 index 00000000..05db9783 --- /dev/null +++ b/chapters/stack/c-assembly-interaction/drills/tasks/max-c-calls-x64/support/Makefile @@ -0,0 +1,25 @@ +CC = gcc +CFLAGS = -g -Wall -Wextra -Werror -fno-pic -masm=intel +ASFLAGS = -f elf64 +LDFLAGS = -no-pie +PROGNAME = mainmax + +ASM = nasm + +.DEFAULT_GOAL: all + +.PHONY: all clean + +all: $(PROGNAME) + +$(PROGNAME): main.o max.o + $(CC) $(LDFLAGS) -o $@ $^ + +max.o: max.asm + $(ASM) $(ASFLAGS) -o $@ $< + +main.o: main.c + $(CC) $(CFLAGS) -c -o $@ $< + +clean: + -rm -f $(PROGNAME) *.o diff --git a/chapters/stack/c-assembly-interaction/drills/tasks/max-c-calls-x64/support/main.c b/chapters/stack/c-assembly-interaction/drills/tasks/max-c-calls-x64/support/main.c new file mode 100644 index 00000000..789368c4 --- /dev/null +++ b/chapters/stack/c-assembly-interaction/drills/tasks/max-c-calls-x64/support/main.c @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#include + +unsigned int get_max(unsigned int *arr, unsigned int len); + +int main(void) +{ + unsigned int arr[] = { 19, 7, 129, 87, 54, 218, 67, 12, 19, 99 }; + unsigned int max; + + max = get_max(arr, 10); + + printf("max: %u\n", max); + + return 0; +} diff --git a/chapters/stack/c-assembly-interaction/drills/tasks/max-c-calls-x64/support/max.asm b/chapters/stack/c-assembly-interaction/drills/tasks/max-c-calls-x64/support/max.asm new file mode 100644 index 00000000..b4767352 --- /dev/null +++ b/chapters/stack/c-assembly-interaction/drills/tasks/max-c-calls-x64/support/max.asm @@ -0,0 +1,26 @@ +; SPDX-License-Identifier: BSD-3-Clause + +section .text + +global get_max + +get_max: + push rbp + mov rbp, rsp + + ; [rbp+16] is array pointer + ; [rbp+24] is array length + + mov rbx, [rbp+16] + mov rcx, [rbp+24] + xor rax, rax + +compare: + cmp eax, [rbx+rcx*4-4] + jge check_end + mov rax, [rbx+rcx*4-4] +check_end: + loopnz compare + + leave + ret diff --git a/chapters/stack/c-assembly-interaction/drills/tasks/max-c-calls/.gitignore b/chapters/stack/c-assembly-interaction/drills/tasks/max-c-calls/.gitignore new file mode 100644 index 00000000..ba2906d0 --- /dev/null +++ b/chapters/stack/c-assembly-interaction/drills/tasks/max-c-calls/.gitignore @@ -0,0 +1 @@ +main diff --git a/chapters/stack/c-assembly-interaction/drills/tasks/max-c-calls/README.md b/chapters/stack/c-assembly-interaction/drills/tasks/max-c-calls/README.md new file mode 100644 index 00000000..7fd07d73 --- /dev/null +++ b/chapters/stack/c-assembly-interaction/drills/tasks/max-c-calls/README.md @@ -0,0 +1,48 @@ +# Maximum Calculation in Assembly with Call from C + +Navigate to `drills/tasks/max-c-calls/support` and open `main.c` + +In this subdirectory you can find an implementation of calculating the maximum of a number where the `main()` function is defined in C from which the `get_max()` function defined in assembly language is called. + +Trace the code in the two files and how the function arguments and return value are passed. + +Compile and run the program. +To compile it run the command: + +```bash +make +``` + +Running the command results in the mainmax executable which we can execute using the command: + +```bash +./mainmax +``` + +> **IMPORTANT:** +> Pay attention to understanding the code before proceeding to the next exercise. + +> **IMPORTANT:** +> The return value of a function is placed in the `eax` register. + +## Maximum Computation Extension in Assembly with Call from C + +Extend the program from the previous exercise (in assembly language and C) so that the `get_max()` function now has the signature `unsigned int get_max(unsigned int *arr, unsigned int len, unsigned int *pos)`. +The third argument to the function is the address where the position in the vector on which the maximum is found will be held. + +The position in the vector on which the maximum is found will also be displayed on display. + +> **TIP:** +> To hold the position, it is best to define a local variable `pos` in the `main()` function in the C file (`main.c`) in the form +> +> ```C +> unsigned int pos; +> ``` +> +> and call the `get_max()` function in the form: +> +> ```C +> max = get_max(arr, 10, &pos); +> ``` + +If you're having difficulties solving this exercise, go through [this relevant section](../../../reading/stack-c-asm.md) reading material. diff --git a/chapters/stack/c-assembly-interaction/drills/tasks/max-c-calls/solution/Makefile b/chapters/stack/c-assembly-interaction/drills/tasks/max-c-calls/solution/Makefile new file mode 120000 index 00000000..a39be4f2 --- /dev/null +++ b/chapters/stack/c-assembly-interaction/drills/tasks/max-c-calls/solution/Makefile @@ -0,0 +1 @@ +../support/Makefile \ No newline at end of file diff --git a/chapters/stack/c-assembly-interaction/drills/tasks/max-c-calls/solution/main.c b/chapters/stack/c-assembly-interaction/drills/tasks/max-c-calls/solution/main.c new file mode 100644 index 00000000..a96358ec --- /dev/null +++ b/chapters/stack/c-assembly-interaction/drills/tasks/max-c-calls/solution/main.c @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#include + +unsigned int get_max(unsigned int *arr, unsigned int len, unsigned int *pos); + +int main(void) +{ + unsigned int arr[] = { 19, 7, 129, 87, 54, 218, 67, 12, 19, 99 }; + unsigned int pos; + + get_max(arr, 10, &pos); + + printf("max: %u\n", arr[pos]); + + return 0; +} diff --git a/chapters/stack/c-assembly-interaction/drills/tasks/max-c-calls/solution/max.asm b/chapters/stack/c-assembly-interaction/drills/tasks/max-c-calls/solution/max.asm new file mode 100644 index 00000000..dd99c1f0 --- /dev/null +++ b/chapters/stack/c-assembly-interaction/drills/tasks/max-c-calls/solution/max.asm @@ -0,0 +1,34 @@ +section .text + +global get_max + +get_max: + push ebp + mov ebp, esp + + ; save ebx in callee + push ebx + + ; [ebp+8] is array pointer + ; [ebp+12] is array length + + mov ebx, [ebp+8] + mov ecx, [ebp+12] + xor eax, eax + +compare: + cmp eax, [ebx+ecx*4-4] + jge check_end + mov eax, [ebx+ecx*4-4] + mov edx, ecx +check_end: + loopnz compare + + dec edx + mov ebx, [ebp+16] + mov [ebx], edx + + pop ebx + + leave + ret diff --git a/chapters/stack/c-assembly-interaction/drills/tasks/max-c-calls/support/Makefile b/chapters/stack/c-assembly-interaction/drills/tasks/max-c-calls/support/Makefile new file mode 100644 index 00000000..c3660e45 --- /dev/null +++ b/chapters/stack/c-assembly-interaction/drills/tasks/max-c-calls/support/Makefile @@ -0,0 +1,20 @@ +CFLAGS = -Wall -g -m32 +ASM = nasm +ASMFLAGS = -f elf32 + +.DEFAULT_GOAL: all + +.PHONY: all clean + +all: main + +main: main.o max.o + $(CC) $(LDFLAGS) -m32 -o $@ $^ + +max.o: max.asm + $(ASM) $(ASMFLAGS) -o $@ $< + +main.o: main.c + +clean: + -rm -f main *.o diff --git a/chapters/stack/c-assembly-interaction/drills/tasks/max-c-calls/support/main.c b/chapters/stack/c-assembly-interaction/drills/tasks/max-c-calls/support/main.c new file mode 100644 index 00000000..789368c4 --- /dev/null +++ b/chapters/stack/c-assembly-interaction/drills/tasks/max-c-calls/support/main.c @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#include + +unsigned int get_max(unsigned int *arr, unsigned int len); + +int main(void) +{ + unsigned int arr[] = { 19, 7, 129, 87, 54, 218, 67, 12, 19, 99 }; + unsigned int max; + + max = get_max(arr, 10); + + printf("max: %u\n", max); + + return 0; +} diff --git a/chapters/stack/c-assembly-interaction/drills/tasks/max-c-calls/support/max.asm b/chapters/stack/c-assembly-interaction/drills/tasks/max-c-calls/support/max.asm new file mode 100644 index 00000000..e44e9fc9 --- /dev/null +++ b/chapters/stack/c-assembly-interaction/drills/tasks/max-c-calls/support/max.asm @@ -0,0 +1,31 @@ +; SPDX-License-Identifier: BSD-3-Clause + +section .text + +global get_max + +get_max: + push ebp + mov ebp, esp + + ; save ebx in callee + push ebx + + ; [ebp+8] is array pointer + ; [ebp+12] is array length + + mov ebx, [ebp+8] + mov ecx, [ebp+12] + xor eax, eax + +compare: + cmp eax, [ebx+ecx*4-4] + jge check_end + mov eax, [ebx+ecx*4-4] +check_end: + loopnz compare + + pop ebx + + leave + ret diff --git a/chapters/stack/c-assembly-interaction/drills/tasks/stack-frame/README.md b/chapters/stack/c-assembly-interaction/drills/tasks/stack-frame/README.md new file mode 100644 index 00000000..40ace510 --- /dev/null +++ b/chapters/stack/c-assembly-interaction/drills/tasks/stack-frame/README.md @@ -0,0 +1,21 @@ +# Corrupt Stack Frame Debugging + +Navigate to `drills/tasks/stack-frame/support` and open `main.c` + +In current subdirectory of the lab's task archive you can find a C program that implements the display of the string `Hello world!` by a call to the `print_hello()` function defined in the assembly for the first part of the message, followed by two calls to the `printf()` function directly from the C code. + +Compile and run the program. +What do you notice? +The printed message is not as expected because the assembly code is missing an instruction. + +Use GDB to inspect the address at the top of the stack before executing the `ret` statement in the `print_hello()` function. +What does it point to? +Track the values of the `ebp` and `esp` registers during the execution of this function. +What should be at the top of the stack after execution of the `leave` statement? + +Find the missing instruction and rerun the executable. + +> **TIP:** +> In order to restore the stack to its state at the start of the current function, the `leave` statement relies on the function's pointer frame having been set. + +If you're having difficulties solving this exercise, go through [this relevant section](../../../reading/stack-c-asm.md) reading material. diff --git a/chapters/stack/c-assembly-interaction/drills/tasks/stack-frame/solution/.gitignore b/chapters/stack/c-assembly-interaction/drills/tasks/stack-frame/solution/.gitignore new file mode 100644 index 00000000..ba2906d0 --- /dev/null +++ b/chapters/stack/c-assembly-interaction/drills/tasks/stack-frame/solution/.gitignore @@ -0,0 +1 @@ +main diff --git a/chapters/stack/c-assembly-interaction/drills/tasks/stack-frame/solution/Makefile b/chapters/stack/c-assembly-interaction/drills/tasks/stack-frame/solution/Makefile new file mode 120000 index 00000000..a39be4f2 --- /dev/null +++ b/chapters/stack/c-assembly-interaction/drills/tasks/stack-frame/solution/Makefile @@ -0,0 +1 @@ +../support/Makefile \ No newline at end of file diff --git a/chapters/stack/c-assembly-interaction/drills/tasks/stack-frame/solution/main.c b/chapters/stack/c-assembly-interaction/drills/tasks/stack-frame/solution/main.c new file mode 100644 index 00000000..8ef7f567 --- /dev/null +++ b/chapters/stack/c-assembly-interaction/drills/tasks/stack-frame/solution/main.c @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#include + +void print_hello(void); + +void asm_call_wrapper(void) +{ + print_hello(); + printf(" world"); +} + + +int main(void) +{ + asm_call_wrapper(); + printf("!\n"); + + return 0; +} diff --git a/chapters/stack/c-assembly-interaction/drills/tasks/stack-frame/solution/print-hello.asm b/chapters/stack/c-assembly-interaction/drills/tasks/stack-frame/solution/print-hello.asm new file mode 100644 index 00000000..ecd3ebfa --- /dev/null +++ b/chapters/stack/c-assembly-interaction/drills/tasks/stack-frame/solution/print-hello.asm @@ -0,0 +1,33 @@ +; SPDX-License-Identifier: BSD-3-Clause + +extern printf + +section .data + message db "Hello", 0 + +section .text + +global print_hello + +print_hello: + push ebp + + ; leave is equivalent to the instruction set: + ; mov esp, ebp + ; pop ebp + ; + ; In the absence of this instruction (saving the current pointer frame), + ; leave would restore the stack tip (esp) to the beginning of the previous frame, + ; above which, on the stack, is an ebp, followed by the return address + ; of the function from which print_hello() was called; thus, when executing + ; the ret statement at the end of print_hello(), it will jump immediately after + ; call of the asm_call_wrapper() function; + + mov ebp, esp + + push message + call printf + add esp, 4 + + leave + ret diff --git a/chapters/stack/c-assembly-interaction/drills/tasks/stack-frame/support/.gitignore b/chapters/stack/c-assembly-interaction/drills/tasks/stack-frame/support/.gitignore new file mode 100644 index 00000000..88d050b1 --- /dev/null +++ b/chapters/stack/c-assembly-interaction/drills/tasks/stack-frame/support/.gitignore @@ -0,0 +1 @@ +main \ No newline at end of file diff --git a/chapters/stack/c-assembly-interaction/drills/tasks/stack-frame/support/Makefile b/chapters/stack/c-assembly-interaction/drills/tasks/stack-frame/support/Makefile new file mode 100644 index 00000000..0a581045 --- /dev/null +++ b/chapters/stack/c-assembly-interaction/drills/tasks/stack-frame/support/Makefile @@ -0,0 +1,21 @@ +CFLAGS = -Wall -g -m32 +ASM = nasm +ASMFLAGS = -f elf32 + +.DEFAULT_GOAL: all + +.PHONY: all clean + +all: main + +main: main.o print_hello.o + $(CC) $(LDFLAGS) -m32 -o $@ $^ + +print_hello.o: print_hello.asm + $(ASM) $(ASMFLAGS) -o $@ $< + +main.o: main.c + $(CC) $(CFLAGS) -c -o $@ $< + +clean: + -rm -f main *.o diff --git a/chapters/stack/c-assembly-interaction/drills/tasks/stack-frame/support/main.c b/chapters/stack/c-assembly-interaction/drills/tasks/stack-frame/support/main.c new file mode 100644 index 00000000..8ef7f567 --- /dev/null +++ b/chapters/stack/c-assembly-interaction/drills/tasks/stack-frame/support/main.c @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#include + +void print_hello(void); + +void asm_call_wrapper(void) +{ + print_hello(); + printf(" world"); +} + + +int main(void) +{ + asm_call_wrapper(); + printf("!\n"); + + return 0; +} diff --git a/chapters/stack/c-assembly-interaction/drills/tasks/stack-frame/support/print_hello.asm b/chapters/stack/c-assembly-interaction/drills/tasks/stack-frame/support/print_hello.asm new file mode 100644 index 00000000..32e18ff4 --- /dev/null +++ b/chapters/stack/c-assembly-interaction/drills/tasks/stack-frame/support/print_hello.asm @@ -0,0 +1,21 @@ +; SPDX-License-Identifier: BSD-3-Clause + +extern printf + +section .data + message db "Hello", 0 + +section .text + +global print_hello + +; TODO: Add the missing instruction +print_hello: + push ebp + + push message + call printf + add esp, 4 + + leave + ret diff --git a/chapters/stack/c-assembly-interaction/reading/stack-c-asm.md b/chapters/stack/c-assembly-interaction/reading/stack-c-asm.md new file mode 100644 index 00000000..46a6e0e8 --- /dev/null +++ b/chapters/stack/c-assembly-interaction/reading/stack-c-asm.md @@ -0,0 +1,58 @@ +# C - Assembly Interaction: Stack + +## Setting the Stack + +When entering a procedure, it is necessary to set a stack frame to which to send parameters. +Of course, if the procedure does not receive parameters, this step is not necessary. So to set the stack, the following code must be included: + +```Assembly +push ebp +mov ebp, esp +``` + +The EBP gives us the ability to use it as an index within the stack and should not be altered during the procedure. + +## Passing Parameters from C to the Assembly Procedure + +C programs send parameters to assembly procedures using the stack. +Consider the following C program sequence: + +```C +#include + +extern int sum(int a, int b); // declare the assembly procedure as external + +int main() { + int a = 5, b = 7; + int res = sum(a, b); // call the assembly procedure + + return 0; +} +``` + +When C executes the call to `sum()`, it first pushes arguments on the stack in reverse order, then actually calls the procedure. +Thus, upon entering the procedure body, the stack will be intact. + +Since the variables `a` and `b` are declared as `int` values, they will each use one word on the stack. +This method of passing parameters is called value passing. +The code of the Sum procedure might look like this: + +```Assembly +section .text + global sum ; declare the procedure label as global + +sum: + push ebp + mov ebp, esp + + mov eax, [ebp+8] ; retrieve the first argument + mov ecx, [ebp+12] ; retrieve the second argument + add eax, ecx ; calculate the sum + + pop ebp + ret +``` + +It is interesting to note several things. +First, the assembly code defaults the return value of the procedure to the `eax` register. +Second, the `ret` command is sufficient to exit the procedure, due to the fact that the C compiler takes care of the rest of the stuff, such as removing parameters from the stack. diff --git a/config.yaml b/config.yaml index 8559e6ea..4c846538 100644 --- a/config.yaml +++ b/config.yaml @@ -94,6 +94,19 @@ lab_structure: - reading/stack.md - guides/stack-operations.md - guides/stack-addressing.md + - title: Lab 10 - The C - Assembly Interaction + filename: lab10.md + content: + - tasks/max-c-calls.md + - tasks/stack-frame.md + - tasks/max-assembly-calls.md + - tasks/regs-preserve.md + - tasks/include-fix.md + - tasks/export-fix.md + - tasks/max-c-calls-x64.md + - tasks/max-assembly-calls-x64.md + - reading/memory-layout-c-asm.md + - reading/stack-c-asm.md - title: Lab 11 - Buffer Management. Buffer Overflow filename: lab11.md content: @@ -187,6 +200,7 @@ docusaurus: - Lab 6 - Registers and Memory Addressing: lab6.md - Lab 7 - Structures, Vectors and Strings: lab7.md - Lab 8 - The Stack: lab8.md + - Lab 10 - The C - Assembly Interaction: lab10.md - Lab 11 - Buffer Management. Buffer Overflow: lab11.md - Lab 12 - Linking: lab12.md - Lab 13 - CTF: lab13.md