You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

无法编写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) or sub 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 at esp/rsp.
  • String Construction: Directly writing each character to the stack with mov byte ensures 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 write doesn'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

火山引擎 最新活动