From bfa32d074533e66334fbbc0db8151ed42db9c0d6 Mon Sep 17 00:00:00 2001 From: Alexander Kuleshov Date: Sat, 7 Mar 2026 18:45:12 +0500 Subject: [PATCH] asm-6: align stack to 16-byte boundary before C function calls The System V AMD64 ABI requires the stack to be 16-byte aligned before calling any C library function. Without proper alignment, C functions like strtod() and printf() can segfault on systems that strictly enforce ABI requirements (e.g., AMD EPYC processors). This fix adds a single instruction at _start to force stack alignment. This ensures RSP % 16 == 0 before any call instruction, which after pushing the 8-byte return address results in RSP % 16 == 8 inside the called function - exactly what the ABI specifies. Signed-off-by: Alexander Kuleshov --- content/asm_6.md | 6 ++++-- float/dot_product.asm | 5 ++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/content/asm_6.md b/content/asm_6.md index 6b80145..de3f017 100644 --- a/content/asm_6.md +++ b/content/asm_6.md @@ -303,11 +303,13 @@ section .text ;; Entry point of the program. _start: + ;; Align stack to 16-byte boundary at start since we are going to call C functions. + and rsp, -16 ;; Jump to the _read_first_float_vector label jmp _read_first_float_vector ``` -The definition of the `.text` section starts from referencing the external functions: `strtod` and `printf`. As mentioned above, these functions are part of the C standard library, and we will use them to simplify our program. After defining the entry point, we immediately jump to the `_read_first_float_vector` label. This is where our code starts. +The definition of the `.text` section starts from referencing the external functions: `strtod` and `printf`. As mentioned above, these functions are part of the C standard library, and we will use them to simplify our program. After defining the entry point, we align the stack to 16 bytes boundary (as System V AMD64 ABI requires before calling C functions) and immediately jump to the `_read_first_float_vector` label. This is where our code starts. Our main goal now is to print the prompt, which will ask a user to type some floating-point values. We will then convert these values from strings to floating-point numbers and store them in a buffer representing our first vector. Let's take a look at the code: @@ -526,7 +528,7 @@ Our result is ready 🎉 🎉 🎉 The last thing to do is to print it. We will ```assembly ;; Specify a reference to the format string for the printf(3) in the rdi register. mov rdi, PRINTF_FORMAT - ;; Number of the floating-point registers passed to printf(3). + ;; Number of the floating-point registers passed to printf(3). ;; We specify `1` because we need to pass only `xmm0` with the result of the program. mov rax, 1 ;; Call the printf(3) function that will print the result. diff --git a/float/dot_product.asm b/float/dot_product.asm index 7b3758a..2084acf 100644 --- a/float/dot_product.asm +++ b/float/dot_product.asm @@ -64,6 +64,9 @@ section .text ;; Entry point of the program. _start: + ;; Align stack to 16-byte boundary at start. + ;; Mask off lower 4 bits to force alignment. + and rsp, -16 ;; Jump to the _read_first_float_vector label jmp _read_first_float_vector @@ -239,7 +242,7 @@ _calculate_dot_product: ;; Specify a reference to the format string for the printf(3) in the rdi register. mov rdi, PRINTF_FORMAT - ;; Number of the floating-point registers passed to printf(3). + ;; Number of the floating-point registers passed to printf(3). ;; We specify `1` because we need to pass only `xmm0` with the result of the program. mov rax, 1 ;; Call the printf(3) function that will print the result.