You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

x86_64 AT&T汇编syscall打印单个ASCII字符失败求助

Why Your x86_64 Write Syscall Isn't Working (And How to Fix It)

Hey Vlad, I see the issue right away—you're misunderstanding how the write syscall expects its arguments! Let's break this down step by step.

The Core Problem: write Needs a Memory Pointer, Not an Immediate Value

On x86_64 Linux, the write syscall (with %rax = 1) expects:

  • %rdi: File descriptor (1 for stdout, which you got right)
  • %rsi: Pointer to a buffer in user-space memory containing the data to print
  • %rdx: Number of bytes to write

Your test code and full code are passing the ASCII value directly into %rsi (like movq $48, %rsi or popq %rsi with the ASCII code). This tells the syscall to read from memory address 0x30 (which is 48 in hex)—but that address is in kernel-reserved space (user-space starts around 0x400000 on most systems). The kernel denies this access, so write returns an error code (-EFAULT), but you're not checking the return value, which is why you see no output and no crash.

Fixing the Print Logic

You need to store your ASCII character in a user-space memory buffer first, then pass the address of that buffer to %rsi. The stack is perfect for this—you can use a small 1-byte buffer on the stack (since you're printing one character at a time).

Here's how to modify your full code's printing_loop:

main:
pushq %rbp
movq %rsp, %rbp
subq $1, %rsp       # Reserve 1 byte of stack space for our character buffer
movq $0, %r9
movq $1234, %rdi

splitting_loop:
movq $0, %rdx
movq %rdi, %rax
movq $10, %rbx
div %rbx
addq $48, %rdx
pushq %rdx
movq %rax, %rdi
incq %r9
cmpq $0, %rdi
jg splitting_loop

printing_loop:
popq %rax               # Pop the ASCII code into %rax
movb %al, -1(%rbp)      # Store the 8-bit character in our stack buffer
movq $1, %rax           # write syscall number
movq $1, %rdi           # stdout file descriptor
leaq -1(%rbp), %rsi     # Load the address of our stack buffer
movq $1, %rdx           # Print 1 byte
syscall
decq %r9
cmpq $0, %r9
jg printing_loop

movq $0, %rdi
call exit

Key Changes Explained:

  1. subq $1, %rsp: Reserves 1 byte of writable user-space memory right at the bottom of our stack frame.
  2. movb %al, -1(%rbp): Takes the 8-bit ASCII character (from %al, the low byte of %rax) and stores it in our stack buffer.
  3. leaq -1(%rbp), %rsi: Loads the address of our stack buffer into %rsi—this is what the write syscall actually expects.

Testing the Fix with Your Minimal Example

If you want to test just printing the '0' character, here's a working version:

.global _start
_start:
pushq %rbp
movq %rsp, %rbp
subq $1, %rsp       # Reserve stack buffer

movb $48, -1(%rbp)  # Store '0' in buffer
movq $1, %rax       # write syscall
movq $1, %rdi       # stdout
leaq -1(%rbp), %rsi # Buffer address
movq $1, %rdx       # 1 byte
syscall

movq $60, %rax      # exit syscall
movq $0, %rdi
syscall

Why You Saw No Crash or Error

Linux's write syscall doesn't crash your program when given an invalid pointer—it just returns -1 (you could check %rax after the syscall to see this error). Since you didn't handle the return value, your program continued executing without any visible feedback.

That should get your integer-to-string code printing correctly! Let me know if you run into any other issues.

内容的提问来源于stack exchange,提问作者Vlad2000Andrei

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:55:46