如何修改ARM汇编代码实现依次请求数字、字符输入并分别打印
ARM汇编代码修改方案
原代码存在的核心问题
- 启动后同时打印数字、字符两个输入提示,不符合「先处理数字输入全流程,再发起字符输入请求」的需求
- 数字打印完成后直接跳转退出,字符读取、打印的逻辑完全无法执行
- 字符读取格式串用
%c会读取输入数字后残留在缓冲区的换行符,导致无需用户输入就直接拿到无效字符 - 寄存器逻辑混乱,读取数字后未打印就提前执行字符读取逻辑,覆盖了r1中存储的数字值,导致数字打印结果错误
修改后的完整代码
@ 使用以下命令对该程序进行汇编、链接、运行和调试: @ as -o student_inputC.o student_inputC.s @ gcc -o student_inputC student_inputC.o @ ./student_inputC @ gdb --args ./student_inputC .equ READERROR, 0 @ 用于检查scanf读取错误。 .global main @ 因使用C库,必须定义main入口。 main: prompt: @ 提示用户输入一个数字。 ldr r0, =strInputPrompt bl printf @ 调用C库printf展示输入提示。 get_num_input: ldr r0, =numInputPattern @ 配置为读取一个整数。 ldr r1, =intInput @ 向r1加载存储输入值的内存地址 bl scanf @ 读取键盘输入。 cmp r0, #READERROR @ 检查是否发生读取错误。 beq readerror @ 若发生读取错误则跳转至对应处理逻辑。 @ 打印输入的数字 ldr r1, =intInput ldr r1, [r1] ldr r0, =strOutputNum bl printf @ 提示用户输入字符 ldr r0, =charInputPrompt bl printf get_char_input: ldr r0, =charInputPattern @ 配置为读取一个字符,前置空格跳过残留空白符 ldr r1, =charInput @ 向r1加载存储输入值的内存地址 bl scanf @ 读取键盘输入。 cmp r0, #READERROR @ 检查是否发生读取错误。 beq readerror @ 若发生读取错误则跳转至对应处理逻辑。 @ 打印输入的字符 ldr r1, =charInput ldr r1, [r1] ldr r0, =strOutputChar bl printf b myexit @ 退出程序。 readerror: @ scanf返回读取错误,清空输入缓冲区后跳转回提示用户重新输入。 @ 由于输入无效,我们需要使用%[^\n]格式读取缓冲区内容直到用户按下回车键,完成输入缓冲区清空。 ldr r0, =strInputPattern ldr r1, =strInputError @ 向r1加载读取内容的存储地址。 bl scanf @ 读取键盘输入。 @ 不对读取的内容做处理,该操作仅用于清空输入缓冲区。 @ 输入缓冲区现已清空,可以重新请求用户输入。 b prompt myexit: @ 代码执行结束,强制退出并将控制权交还给操作系统 mov r7, #0x01 @ 退出指令的SVC调用号 svc 0 @ 发起系统调用。 .data @ 声明所需的字符串和数据 .balign 4 strInputPrompt: .asciz "Input the number: \n" .balign 4 strOutputNum: .asciz "The number value is: %d \n" .balign 4 charInputPrompt: .asciz "Input the character: \n" .balign 4 strOutputChar: .asciz "The character is: %c \n" @ scanf调用的格式串 .balign 4 numInputPattern: .asciz "%d" @ 读取整数的格式串。 .balign 4 strInputPattern: .asciz "%[^\n]" @ 用于清空无效输入对应的输入缓冲区。 .balign 4 strInputError: .skip 100*4 @ 用于存储清空输入缓冲区时读取的无效内容。 .balign 4 intInput: .word 0 @ 存储用户输入数字的内存位置。 .balign 4 charInputPattern: .asciz " %c" @ 读取字符的格式串,前置空格跳过空白符。 .balign 4 charInput: .word 0 @ 存储用户输入字符的内存位置 @ 告知汇编器以下为C库函数 .global printf @ printf使用说明: @ r0 - 待打印字符串的起始地址,字符串必须符合C编码标准。 @ r1 - 若字符串包含输出参数(如%d、%c等),r1必须存储待打印的数值。 @ 调用返回后r0、r1、r2、r3、r12寄存器的值会被修改。 .global scanf @ scanf使用说明: @ r0 - 读取用户输入值所用的输入格式串地址,本示例中为numInputPattern。 @ r1 - 必须存储输入值的存储地址,本示例使用.data段声明的intInput内存位置。 @ 调用返回后r0、r1、r2、r3、r12寄存器的值会被修改。 @ scanf重要说明: @ 若用户输入与输入格式不匹配,寄存器r0将返回0,格式合法则返回1。无效输入不会被自动从输入缓冲区清除,因此执行其他操作前需要手动清空缓冲区。 @ @ scanf与输入格式的附加说明: @ 1. 若使用%s或%c格式,用户输入不会产生错误码,用户在键盘输入的任何内容都会被这两种格式接受。 @ 2. 若使用%d格式,用户输入12.123时,scanf会将12识别为有效输入,剩余的.123会留在输入缓冲区中。 @ 3. 若使用"%c"格式,所有空白字符会保留在输入缓冲区中,多数情况下用户输入的回车键会留在缓冲区,若下次再用"%c"格式读取会直接返回该回车符。若要忽略这些空白字符,可以使用" %c"作为输入格式,会自动跳过用户输入的所有非打印字符。 @ @ 代码结束,文件末尾请保留一行空行。
关键修改说明
- 调整了提示语打印时机:进入流程后仅打印数字输入提示,数字读取、打印全流程完成后,再打印字符输入提示
- 拆分了数字、字符的输入读取逻辑,删除了数字打印后直接跳转退出的错误指令,保证字符处理逻辑可以正常执行
- 修改字符读取格式串为
%c,前置空格自动跳过输入数字后残留在缓冲区的换行符等空白字符,避免直接读取到无效换行符 - 调整寄存器使用逻辑,数字读取完成后先完成打印再处理字符相关逻辑,避免数字值被提前覆盖导致打印错误
- 保留了原有的输入错误处理逻辑,数字、字符输入出错时都会清空缓冲区重新发起输入请求
内容的提问来源于stack exchange,提问作者MaciG
相关产品推荐
相关产品推荐

