汇编程序终端持续重复输出内容,无法正常接收输入问题排查
问题:x86-64汇编程序重复输出菜单,无法等待用户输入
我编写了一段x86-64汇编程序,预期显示菜单后等待用户输入选择,但运行时终端持续重复输出菜单内容,无法正常停留在输入环节。
程序代码
section .bss choice resb 4 ; Buffer for storing user choice ans resb 32 section .text global _start _start: loop: ;welcome msg mov rax, 1 mov rdi, 1 mov rsi, text1 mov rdx, text1_len syscall ;menu mov rax, 1 mov rdi, 1 mov rsi, c1 mov rdx, c1_len syscall mov rax, 1 mov rdi, 1 mov rsi, c2 mov rdx, c2_len syscall mov rax, 1 mov rdi, 1 mov rsi, c3 mov rdx, c3_len syscall mov rax, 1 mov rdi, 1 mov rsi, c4 mov rdx, c4_len syscall mov rax, 1 mov rdi, 1 mov rsi, c5 mov rdx, c5_len syscall mov rax, 1 mov rdi, 1 mov rsi, text2 mov rdx, text2_len syscall ;gets choice mov rax, 0 mov rdi, 0 mov rsi, choice mov rdx, 4 syscall ;ends code there (i just wanted to test if it worked before i move on) mov rax, 60 mov rdi, 0 syscall section .data text1 db "Hello welcome to math help", 0xA c1 db "(1) Add", 0xA c2 db "(2) Subtract", 0xA c3 db "(3) Multiply", 0xA c4 db "(4) Divide", 0xA c5 db "(0) Exit", 0xA text2 db "Please enter your choice below", 0xA text1_len equ $ - text1 c1_len equ $ - c1 c2_len equ $ - c2 c3_len equ $ - c3 c4_len equ $ - c4 c5_len equ $ - c5 text2_len equ $ - text2
终端输出
Hello welcome to math help (1) Add (2) Subtract (3) Multiply (4) Divide (0) Exit Please enter your choice below (1) Add (2) Subtract (3) Multiply (4) Divide (0) Exit Please enter your choice below (2) Subtract (3) Multiply (4) Divide (0) Exit Please enter your choice below (3) Multiply (4) Divide (0) Exit Please enter your choice below (4) Divide (0) Exit Please enter your choice below (0) Exit Please enter your choice below Please enter your choice below
问题原因及解决方法
核心原因
你大概率使用了错误的编译格式,将程序编译成了**flat binary(纯二进制文件)**而非标准ELF64可执行文件。flat binary格式下,代码段(.text)和数据段(.data)会连续存储在内存中,且整个文件被标记为可执行。当程序执行完exit系统调用后,若退出逻辑出现异常,程序计数器会继续执行.data段的字符串内容,将其当作机器指令运行,最终导致重复输出菜单等异常行为。
同时,代码中section的顺序不符合常规规范,也会加剧这类问题的出现。
解决步骤
正确编译为ELF64格式
使用以下命令编译链接程序:nasm -f elf64 your_program.asm -o your_program.o ld your_program.o -o your_programELF格式会将代码段、数据段、未初始化数据段(
.bss)分隔到独立的内存区域,数据段会被标记为不可执行,从根源避免字符串被当作指令执行的问题。调整section顺序(可选但推荐)
将section顺序调整为.data→.bss→.text,符合汇编代码的常规结构,减少潜在的内存布局问题:section .data ; 所有数据定义放在这里 section .bss ; 所有未初始化数据定义放在这里 section .text global _start _start: ; 代码逻辑放在这里优化输入读取(可选)
你只需要读取用户的单个选择字符,因此可以将read系统调用的缓冲区长度从4改为1,避免不必要的内存占用和潜在的缓冲区溢出:;gets choice mov rax, 0 mov rdi, 0 mov rsi, choice mov rdx, 1 ; 只读取1个字节 syscall
内容的提问来源于stack exchange,提问作者David Roman
相关产品推荐
相关产品推荐

