将预留数据存入寄存器后入栈、清空数据再出栈打印的问题排查
问题排查与修正
核心问题
你代码的核心错误是混淆了内存地址和数据本身:你推入栈中的是buf的内存地址,而非buf中存储的实际数据。后续清空buf后,弹出的依然是buf的地址,但此时该地址指向的内存内容已经被清空,自然无法打印出预期数据。
错误细节分析
- 栈操作逻辑错误:
执行mov rax, buf时,是把buf的起始地址加载到rax寄存器,而非buf中的数据。随后push rax只是把这个地址推入栈,完全没有实现“将预留数据推入栈”的需求。 - 打印逻辑的隐性问题:
write系统调用要求rsi参数指向要输出的数据内存地址。你弹出栈中的地址到rsi后,该地址指向的buf已经被clearBuf清空,所以输出为空。
修正后的代码
以下是符合需求的修正版本,核心改动是将buf的数据推入栈而非地址,同时调整打印逻辑:
section .text global _start _start: mov rcx, mesLen mov rbx, message mov rax, 0 mov r8, 0 loop1: ; fill buffer mov dl, byte [rbx+rax] mov byte [buf+r8], dl ; Use r8 as an index for the buffer inc rax inc r8 cmp rax, rcx ; Compare rax with rcx to check the end of the message jl loop1 ; 将buf中的数据加载到rax,推入栈中(而非buf的地址) mov rax, [buf] push rax ; 清空buf call clearBuf ; 从栈中弹出数据到rax,存入临时内存用于打印 pop rax mov [temp_buf], rax ; 打印弹出的数据 mov rax, 1 mov rdi, 1 mov rsi, temp_buf mov rdx, 8 syscall call newLineFunc ; 退出程序 mov rax, 60 xor rdi, rdi syscall newLineFunc: mov rax, 1 mov rdi, 1 mov rsi, newLine mov rdx, 1 syscall ret clearBuf: dec r8 mov byte [buf+r8], 0 jnz clearBuf ret section .data message db "42" mesLen equ $-message newLine db 10 section .bss buf resb 8 temp_buf resb 8 ; 新增临时内存,用于存储弹出的数据
额外说明
clearBuf函数的逻辑是正确的,它会将buf中被写入的字节全部清空为0;- 新增
temp_buf是因为write系统调用需要读取内存地址的数据,无法直接使用寄存器中的值作为输出源; - 如果只需要打印
message的内容(比如"42"),可以调整rdx的值为mesLen(即2),避免打印多余的空字节。
内容的提问来源于stack exchange,提问作者koma
相关产品推荐
相关产品推荐

