Created by paolieri@usc.edu for the enjoyment of all students of CS356: Introduction to
Computer Systems.
To contribute new examples, create a pull request.
-
Write a header file with the prototype of your function, for example
src/add_two_integers.h
containing:/* src/add_two_integers.h */ int add_two_integers(int x, int y);
-
Write an assembly implementation for this function in
src/add_two_integers_x64.s
(using x86-64 assembly) orsrc/add_two_integers_a64.s
(using ARM64 assembly), or both, for example:/* src/add_two_integers_x64.s */ .globl add_two_integers add_two_integers: movl %edi,%eax addl %esi,%eax ret
/* src/add_two_integers_a64.s */ .global add_two_integers add_two_integers: add w0, w0, w1 ret
-
Write a test for your implementation in
test/test_add_two_integers.c
:/* test/test_add_two_integers.c */ #include "unity.h" #include "add_two_integers.h" void setUp(void) { } void tearDown(void) { } void test_add(void) { TEST_ASSERT_EQUAL(7, add_two_integers(4, 3)); } int main(void) { UNITY_BEGIN(); RUN_TEST(test_add); return UNITY_END(); }
-
Compile and link each implementation with the test into an executable:
$ make bin/test_add_two_integers_x64 cc -Wall -Wextra -std=c17 -MMD -MP -Og -g -Isrc -c test/test_add_two_integers.c -o build/test_add_two_integers_x64.o cc -Wall -Wextra -std=c17 -MMD -MP -Og -g -Isrc -c src/add_two_integers_x64.s -o build/add_two_integers_x64.o cc -Wall -Wextra -std=c17 -MMD -MP -Og -g -Isrc -c test/unity.c -o build/unity_x64.o cc -Wall -Wextra -std=c17 -MMD -MP -Og -g -Isrc build/test_add_two_integers_x64.o build/add_two_integers_x64.o build/unity_x64.o -o bin/test_add_two_integers_x64 $ make bin/test_add_two_integers_a64 aarch64-linux-gnu-gcc -static -Wall -Wextra -std=c17 -MMD -MP -Og -g -Isrc -c test/test_add_two_integers.c -o build/test_add_two_integers_a64.o aarch64-linux-gnu-gcc -static -Wall -Wextra -std=c17 -MMD -MP -Og -g -Isrc -c src/add_two_integers_a64.s -o build/add_two_integers_a64.o aarch64-linux-gnu-gcc -static -Wall -Wextra -std=c17 -MMD -MP -Og -g -Isrc -c test/unity.c -o build/unity_a64.o aarch64-linux-gnu-gcc -static -Wall -Wextra -std=c17 -MMD -MP -Og -g -Isrc build/test_add_two_integers_a64.o build/add_two_integers_a64.o build/unity_a64.o -o bin/test_add_two_integers_a64
-
Run the implementation tests:
$ ./bin/test_add_two_integers_x64 test/test_add_two_integers.c:13:test_add:PASS ----------------------- 1 Tests 0 Failures 0 Ignored OK $ ./bin/test_add_two_integers_a64 test/test_add_two_integers.c:13:test_add:PASS ----------------------- 1 Tests 0 Failures 0 Ignored OK
You can also compile and run all tests (for all implementations) with make test
.
- Test results are saved in
.res
files insidetest
(e.g.,test/test_add_two_integers.res
). - If you modify an implementation or a test, running
make test
recompiles that test and regenerates its.res
file.
This can be useful to check the ARM64 assembly code generated by GCC.
# compile a C program as arm64 (must have a main)
aarch64-linux-gnu-gcc -static -Og -g hello.c -o hello
# check the generated assembly
aarch64-linux-gnu-objdump -d hello
# runs arm64 binary on x86-64 Linux (cool!)
./hello
# debug it
qemu-aarch64 -g 12345 ./hello
gdb-multiarch ./hello -ex 'target remote :12345'