{"id":16161420,"url":"https://github.com/gamemann/c-to-assembly-tests","last_synced_at":"2025-03-18T22:30:47.771Z","repository":{"id":92735436,"uuid":"364925368","full_name":"gamemann/C-To-Assembly-Tests","owner":"gamemann","description":"A repository that stores results from converting C code to Assembly. I use this repository to analyze performance with my C code.","archived":false,"fork":false,"pushed_at":"2024-05-28T22:50:38.000Z","size":1295,"stargazers_count":20,"open_issues_count":0,"forks_count":2,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-02-28T12:30:16.745Z","etag":null,"topics":["assembler","assembly","c","clang","dump","gcc","intel","jit","llc","llvm","obj","objdump","optimization","perf","performance","x86","x86-64"],"latest_commit_sha":null,"homepage":"https://deaconn.net/","language":"Assembly","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gamemann.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-05-06T13:45:42.000Z","updated_at":"2025-02-16T12:55:32.000Z","dependencies_parsed_at":null,"dependency_job_id":"a4e1dd62-586c-47b8-84f8-7ecda6bcfab0","html_url":"https://github.com/gamemann/C-To-Assembly-Tests","commit_stats":{"total_commits":52,"total_committers":1,"mean_commits":52.0,"dds":0.0,"last_synced_commit":"89d424bfe4835fc9404b7f8124d128a0d00e4028"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gamemann%2FC-To-Assembly-Tests","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gamemann%2FC-To-Assembly-Tests/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gamemann%2FC-To-Assembly-Tests/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gamemann%2FC-To-Assembly-Tests/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gamemann","download_url":"https://codeload.github.com/gamemann/C-To-Assembly-Tests/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243950878,"owners_count":20373664,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["assembler","assembly","c","clang","dump","gcc","intel","jit","llc","llvm","obj","objdump","optimization","perf","performance","x86","x86-64"],"created_at":"2024-10-10T02:25:12.751Z","updated_at":"2025-03-18T22:30:47.146Z","avatar_url":"https://github.com/gamemann.png","language":"Assembly","funding_links":[],"categories":[],"sub_categories":[],"readme":"This repository stores both C and Assembly code. There are Bash scripts in the [`scripts/`](./scripts) directory that automatically converts all C source files in the [`src/`](./src) directory to Assembly code and stores the results in the [`asm/`](./asm) directory. The Bash scripts build the C source files using both GCC and Clang along with optimization levels 0 - 3.\n\n## My Motives\nI enjoy low-level optimization in C and often refer back to this repository when wanting to analyze performance with my C code. High performance is required for many applications I make in C, especially firewalls and packet processing software. While I wouldn't consider myself an expert at low-level optimization, but I want to continue learning in hopes I'll eventually become very efficient with it.\n\n## C Source Files\nThe following C source files are included in the [`src/`](./src) directory.\n\n| File Name | Description |\n| --------- | ----------- |\n| `8to64.c` | Casts from a u8 array to u64. |\n| `16to64.c` | Casts from a u16 array to u64. |\n| `32to64.c` | Casts from a u32 array to u64. |\n| `64.c` | Prints a 64-bit integer. |\n| `64_2.c` | Creates a 64-bit integer along with a pointer referencing it and prints the pointer real value. |\n| `64to8.c` | Creates a 64-bit and stores it in a u8 array. |\n| `64to16.c` | Creates a 64-bit and stores it in a u16 array. |\n| `64to32.c` | Creates a 64-bit and stores it in a u32 array. |\n| `empty.c` | A completely empty C program. |\n| `forloop.c` | Creates an 8-byte array and prints each byte through a for loop. |\n| `fprintf.c` | Prints to stdout via `fprintf()`. |\n| `if_simple.c` | Create an integer and performs a simple if check that prints to stdout. |\n| `if.c` | Create an integer and checks against 6 values. |\n| `matchrs.c` | Creates a 32-bit integer and performs bit-wise operations. |\n| `matchstruct.c` | Sets flags within a structure and checks. If successful, prints to stdout. |\n| `memcpy.c` | Copies an 8-byte array using `memcpy()`. |\n| `nullptr.c` | Initializes a null pointer and prints to stdout based off of the value of the null pointer. |\n| `perftest1_one.c` | Initializes an one-byte integer and performs addition/division. Afterwards. prints to stdout. |\n| `perftest1_two.c` | Initializes a standard integer (likely four bytes) and performs addition/division. Afterwards. prints to stdout. |\n| `perftest2_one.c` | Initializes a large data structure and passes to a no-inlined function by value along with prints the fields to stdout. |\n| `perftest2_two.c` | Initializes a large data structure and passes to a no-inlined function by reference along with prints the fields to stdout. |\n| `perftest3_one.c` | Initializes a data structure with all 0's, sets a few fields, and then passes it to a non-inlined function along with prints the values. |\n| `perftest3_two.c` | Initializes a data structure with fields representing typical padding added by the compiler, sets the fields (including padding fields) all at once, and then passes it to a non-inlined function along with prints the values. |\n| `pointer_reassign.c` | Initializes an integer and pointer that points to it then reassigns again and prints value. |\n| `pointer.c` | Initializes an integer and pointer that points to it then prints value. |\n| `print.c` | Prints string constant, creates a new character array, copies constant to it, and prints new array. |\n| `printf.c` | Prints to stdout via `printf()`. |\n| `switch_simple.c` | Creates an integer and performs a single switch case. If matched, prints to stdout. |\n| `switch.c` | Creates an integer and performs 6 switch cases. If matched, prints to stdout. |\n| `switch.c` | Creates an integer and performs 6 switch cases. If matched, prints to stdout. |\n| `unroll_not_test.c` | Creates an integer and a loop that executes 256 times. Each loop iteration adds onto integer by `j * 2`. Afterwards, prints to stdout. |\n| `unroll_simple_not.c` | Creates an integer and a loop that executes 100 times. Each loop iteration adds onto integer by `i * 5`. Afterwards, prints to stdout. |\n| `unroll_simple_not.c` | Creates an integer and a loop that executes 100 times. Each loop iteration adds onto integer by `i * 5`. Afterwards, prints to stdout. |\n| `unroll_simple.c` | Creates an integer and a loop (unrolled) that executes 100 times. Each loop iteration adds onto integer by `i * 5`. Afterwards, prints to stdout. |\n| `unroll_test.c` | Creates an integer and a loop (unrolled by 10) that executes 256 times. Each loop iteration adds onto integer by `j * 2`. Afterwards, prints to stdout. |\n| `xdp_adjust_head.c` | Performs `bpf_xdp_adjust_head()` function inside of a XDP program. |\n| `xdp_adjust_tail.c` | Performs `bpf_xdp_adjust_tail()` function inside of a XDP program. |\n| `xdp_adjust_head.c` | Performs `bpf_xdp_adjust_head()` function inside of a XDP program. |\n| `xdp_block_port8080.c` | A XDP program that drops and blocks source IPs when packets arrive on TCP destination port 8080. |\n| `xdp_drop_port8080.c` | A XDP program that drops packets when packets arrive on TCP destination port 8080. |\n| `xdp_redefine.c` | A XDP program that initializes ethernet, IP, and TCP headers and then reinitializes and checks again. |\n| `xdp_simple_check_unlikely.c` | A XDP program that initializes ethernet, IP, and TCP headers and uses `unlikely()` to check if the header is valid. |\n| `xdp_simple_check.c` | A XDP program that initializes ethernet, IP, and TCP headers and checks if the header is valid. |\n| `xdp_simple_drop.c` | A XDP program that returns `XDP_DROP` immediately |\n| `xdp_simple_pass.c` | A XDP program that returns `XDP_PASS` immediately |\n\nMore C source files will be added as time goes on and I need to test different things.\n\n**NOTE** - I want to revamp file names and source files for organization in the future since it's a bit messy right now. However, I don't have the time to revamp the entire repository since a lot of these programs date back to years ago when I was new-ish to C.\n\n## Generating Assembly Code\nI'd recommend using the [`scripts/gensrcdir.sh`](./scripts/gensrcdir.sh) Bash script I made to generate Assembly code under different compilers (GCC and Clang) and optimization levels (0 - 4) under all C source files in the [`src/`](./src) directory. There are also both non-Intel and Intel architecture dumps included.\n\nYou may also use the [`scripts/genassembly.sh`](./scripts/genassembly.sh) Bash script to convert a single source file which only requires one argument which is the name of the source file in [`src/`](./src) directory without the file extension (`.c`). Also make sure to modify the `ROOTDIR` variable if you place the script outside of this repository's `scripts/` directory. An example may be found below.\n\n```bash\n./genassembly.sh pointer\n```\n\n## Optimization Levels\nHere is general information on the different optimization levels for Clang. Please keep in mind optimization levels may be different for GCC.\n\n```\nCode Generation Options\n    -O0, -O1, -O2, -O3, -Ofast, -Os, -Oz, -Og, -O, -O4\n    Specify which optimization level to use:\n        -O0  Means “no optimization”: this level compiles the fastest\n        and generates the most debuggable code.\n\n        -O1 Somewhere between -O0 and -O2.\n\n        -O2 Moderate level of optimization which enables  most  opti‐\n        mizations.\n\n        -O3  Like -O2, except that it enables optimizations that take\n        longer to perform or that may generate  larger  code  (in  an\n        attempt to make the program run faster).\n\n        -Ofast  Enables  all  the  optimizations  from -O3 along with\n        other aggressive optimizations that may violate  strict  com‐\n        pliance with language standards.\n\n        -Os Like -O2 with extra optimizations to reduce code size.\n\n        -Oz Like -Os (and thus -O2), but reduces code size further.\n\n        -Og  Like  -O1. In future versions, this option might disable\n        different optimizations in order to improve debuggability.\n\n        -O Equivalent to -O2.\n\n        -O4 and higher\n            Currently equivalent to -O3\n```\n\nYou'll notice a lot of optimizations within the Assembly code from `-O1` to `-O3`.\n\n## System\nThis was all tested on my Linux VM running `virtio_net` drivers and Debian 12. The Linux kernel the tests in `asm/` were built with was `6.1.0-13`.\n\n## Credits\n* [Christian Deacon](https://github.com/gamemann)","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgamemann%2Fc-to-assembly-tests","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgamemann%2Fc-to-assembly-tests","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgamemann%2Fc-to-assembly-tests/lists"}