x86_64 AT&T汇编syscall打印单个ASCII字符失败求助
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:
subq $1, %rsp: Reserves 1 byte of writable user-space memory right at the bottom of our stack frame.movb %al, -1(%rbp): Takes the 8-bit ASCII character (from%al, the low byte of%rax) and stores it in our stack buffer.leaq -1(%rbp), %rsi: Loads the address of our stack buffer into%rsi—this is what thewritesyscall 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

