无法编写Linux下X86汇编syscall:如何在栈中构建字符串并调用
x86 Assembly: Build "Hello World" on the Stack and Use Linux Syscalls
Got it, let's work through this! You want to skip the .rodata section entirely and construct the "Hello World" string directly on the stack before invoking Linux system calls—this is a great way to get hands-on with stack memory and syscall conventions. Below are both 32-bit and 64-bit x86 implementations that mirror your C code's behavior perfectly.
32-bit x86 Implementation (NASM Syntax)
This targets 32-bit Linux systems, using the classic int 0x80 syscall interface:
section .text global _start _start: ; Reserve 12 bytes on the stack (matches char string[12] in your C code) sub esp, 12 ; Populate the stack with each character of "Hello World\0" mov byte [esp], 'H' mov byte [esp+1], 'e' mov byte [esp+2], 'l' mov byte [esp+3], 'l' mov byte [esp+4], 'o' mov byte [esp+5], ' ' mov byte [esp+6], 'W' mov byte [esp+7], 'o' mov byte [esp+8], 'r' mov byte [esp+9], 'l' mov byte [esp+10], 'd' mov byte [esp+11], 0x00 ; Null terminator (matches your C code, though write doesn't need it) ; Prepare arguments for write() syscall mov ebx, 1 ; File descriptor: 1 = stdout mov ecx, esp ; Pointer to our stack-allocated string mov edx, 11 ; Number of bytes to write (skip the null terminator) mov eax, 4 ; 32-bit Linux syscall number for write() int 0x80 ; Trigger the syscall ; Exit the program cleanly mov eax, 1 ; 32-bit Linux syscall number for exit() mov ebx, 0 ; Exit status code: 0 = success int 0x80
64-bit x86 Implementation (NASM Syntax)
For modern 64-bit Linux systems, we use the syscall instruction and updated register conventions:
section .text global _start _start: ; Reserve 12 bytes on the stack (stack stays 16-byte aligned, which is required for 64-bit) sub rsp, 12 ; Populate the stack with "Hello World\0" mov byte [rsp], 'H' mov byte [rsp+1], 'e' mov byte [rsp+2], 'l' mov byte [rsp+3], 'l' mov byte [rsp+4], 'o' mov byte [rsp+5], ' ' mov byte [rsp+6], 'W' mov byte [rsp+7], 'o' mov byte [rsp+8], 'r' mov byte [rsp+9], 'l' mov byte [rsp+10], 'd' mov byte [rsp+11], 0x00 ; Prepare arguments for write() syscall (64-bit convention) mov rdi, 1 ; File descriptor: 1 = stdout mov rsi, rsp ; Pointer to stack string mov rdx, 11 ; Byte count mov rax, 1 ; 64-bit Linux syscall number for write() syscall ; Trigger the syscall ; Exit the program mov rax, 60 ; 64-bit syscall number for exit() mov rdi, 0 ; Exit status 0 syscall
Quick Breakdown:
- Stack Allocation: We use
sub esp, 12(32-bit) orsub rsp, 12(64-bit) to carve out space for the 12-byte string. Since the stack grows downward, this creates a contiguous memory block starting atesp/rsp. - String Construction: Directly writing each character to the stack with
mov byteensures we never touch read-only data sections. - Syscall Differences: 32-bit and 64-bit Linux use distinct syscall numbers and register argument orders—double-check which architecture you're targeting.
- Null Terminator: We include it to match your C code, but
writedoesn't require it (we explicitly pass the length 11 to skip it).
To assemble and run the 64-bit version:
nasm -f elf64 hello-stack.asm -o hello-stack.o ld hello-stack.o -o hello-stack ./hello-stack
内容的提问来源于stack exchange,提问作者Alvin




