Win10+Cygwin环境下x64 Windows汇编控制台打印字符串求助
Got it, let's tackle how to print a string to the Windows x64 console using NASM and GCC under Cygwin. Since x64 Windows assembly resources are indeed scarce compared to Linux x64 or 32-bit Windows, I'll walk you through complete, working examples step by step.
First, Understand x64 Windows Calling Conventions
Before diving into code, let's lock in the critical details:
- x64 Windows uses the fastcall convention: the first 4 arguments are passed in registers
RCX,RDX,R8,R9(in order). Any additional arguments go on the stack. - You must reserve 32 bytes of "shadow space" on the stack before calling any WinAPI function (this gives the called function space to save the first 4 register arguments if needed).
- The stack must be aligned to a 16-byte boundary before making a function call.
Example 1: Standalone Assembly Program
This is a pure NASM program that prints a string directly to the console using WinAPI functions.
Step 1: Write the Assembly Code (print.asm)
section .data ; Our message plus Windows-style line ending (CRLF) msg db 'Hello, x64 Windows Console!', 0Dh, 0Ah ; Calculate message length automatically msg_len equ $ - msg section .text ; Declare main as the entry point (GCC expects this) global main ; Import required WinAPI functions from kernel32.dll extern GetStdHandle extern WriteConsoleA extern ExitProcess main: ; Reserve 64 bytes on stack: 32 bytes shadow space + alignment to 16 bytes sub rsp, 40h ; 1. Get the standard output handle ; GetStdHandle(-11) = STD_OUTPUT_HANDLE mov rcx, -11 call GetStdHandle ; Store the handle in RBX (non-volatile register, safe to keep) mov rbx, rax ; 2. Write the message to console ; WriteConsoleA(handle, buffer, length, &bytes_written, NULL) mov rcx, rbx ; 1st arg: stdout handle mov rdx, msg ; 2nd arg: message buffer mov r8, msg_len ; 3rd arg: message length lea r9, [rsp + 20h] ; 4th arg: pointer to track bytes written (uses shadow space) mov qword [rsp + 30h], 0 ; 5th arg: NULL (goes on stack, since it's beyond 4 args) call WriteConsoleA ; 3. Exit the process cleanly mov rcx, 0 ; Exit code 0 (success) call ExitProcess
Step 2: Compile and Link with Cygwin
Run these commands in your Cygwin terminal:
# Assemble the NASM code into a Windows object file nasm -f win64 print.asm -o print.obj # Link the object file into an executable, linking against kernel32.dll gcc print.obj -o print.exe -lkernel32
Step 3: Run the Program
Just execute the generated .exe file:
./print.exe
Example 2: C + Assembly Hybrid Program
If you prefer to handle most logic in C but use assembly for low-level tasks like console output, here's a mixed example.
Step 1: Write the Assembly Helper (asm_print.asm)
section .data ; Reusable CRLF line ending crlf db 0Dh, 0Ah crlf_len equ $ - crlf section .text ; Import WinAPI functions extern GetStdHandle extern WriteConsoleA ; Declare the function so C can call it global asm_print ; Function signature: void asm_print(const char* str, size_t len) asm_print: ; Reserve shadow space + align stack sub rsp, 40h ; Save input arguments (RCX = str, RDX = len) to non-volatile registers mov r8, rcx mov r9, rdx ; Get stdout handle mov rcx, -11 call GetStdHandle ; Write the input string mov rcx, rax ; Handle mov rdx, r8 ; String buffer mov r8, r9 ; String length lea r9, [rsp + 20h] ; Bytes written pointer mov qword [rsp + 30h], 0 ; NULL call WriteConsoleA ; Write a newline after the string mov rcx, rax mov rdx, crlf mov r8, crlf_len lea r9, [rsp + 20h] mov qword [rsp + 30h], 0 call WriteConsoleA ; Restore stack and return to C add rsp, 40h ret
Step 2: Write the C Wrapper (main.c)
#include <stddef.h> // Declare the assembly function for C void asm_print(const char* str, size_t len); int main() { const char* msg = "Hello from C calling x64 Windows assembly!"; // Call our assembly function to print the string asm_print(msg, 43); return 0; }
Step 3: Compile and Link
nasm -f win64 asm_print.asm -o asm_print.obj gcc main.c asm_print.obj -o mixed.exe -lkernel32
Key Notes to Remember
- The
-lkernel32flag tells GCC to link againstkernel32.dll, which contains all the WinAPI functions we use. - Stack alignment is non-negotiable in x64 Windows. If you skip it, your program will crash unpredictably.
WriteConsoleAis the ANSI version of the function; if you need Unicode support, useWriteConsoleWand wide strings.
内容的提问来源于stack exchange,提问作者Eagterrian Knight




