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

如何修复汇编代码中反转5字符字符串时出现的段错误?

ARM汇编字符串反转问题:原串输出+段错误修复

尝试编写ARM汇编代码反转用户输入的5字符字符串,结果程序不仅只打印原字符串,还触发segmentation error(段错误)。原代码如下:

.data // start of the data segment
input:
    .space 100
inputSize = .-input
prompt:
    .asciz "Enter a string with 5 characters"
promptSize = .-prompt
reversed:
    .space 100
reversedSize = .-reversed
.text // start o the text segment (Code)
.global _start // Linux Standard _start, similar to main in C/C++
_start:
// Display prompt message
mov x0, #0          // stdout
ldr x1, =prompt      // store the address of flow into x1
ldr x2, =promptSize      // store the size of the flowwWorld string into x2
mov x8, #64         // store 64 to x8, this is the linux write call
svc 0  
mov x0, #1 // file descriptor for stdin
ldr x1, =input      // store the address of flow into x1
ldr x2, =inputSize
mov x8, #63 // system call number for read
svc 0
mov x0, #1 // file descriptor for stdout
ldr x1, =input // address of input buffer
mov x2, #100 // maximum number of bytes to write
mov x8, #64 // system call number for write
svc 0
// Reverse the input string
mov x1, #0        // set x1 to 0 to represent the start of the input string
add x2, x2, #-2  // set x2 to the second-to-last index in the input string
mov x4, #0
loop: 
  cmp x4, #2
  b.gt end
  ldrb w3, [x1], #1  // load byte from input string starting from the left
  ldrb w4, [x2], #-1 // load byte from input string starting from the right
  strb w4, [x1, #-1] // store right byte at the left index
  strb w3, [x2, #1]  // store left byte at the right index
  add x4, x4, 1
  b loop             // jump to loop
end:
// Display the reversed string
mov x0, #0          // stdout
ldr x1, =input      // store the address of input into x1
ldr x2, =inputSize  // store the size of the input string into x2
mov x8, #64         // store 64 to x8, this is the linux write call
svc 0
// Exit to the OS, essentially this code does this in c
// return 0;
mov x0, #0          // return value
mov x8, #93         // Service call code
svc 0   

错误原因拆解

原代码的核心问题集中在输入输出逻辑、指针初始化和寄存器冲突上:

  1. 文件描述符搞反:stdout的文件描述符是1,原代码把提示输出写到了stdin(x0=#0);读取输入时又用了stdout(x0=#1),导致输入根本没被正确读到缓冲区里。
  2. 指针指向非法内存:反转逻辑里把x1设为0,直接访问内存地址0,必然触发段错误;而且x2被之前的mov x2, #100覆盖,根本不是输入字符串的实际长度,索引计算完全错误。
  3. 寄存器被非法覆盖:循环计数器x4被用来存储读取的右字节,导致循环条件判断混乱,循环逻辑失效。
  4. 输出参数错误:反转后的字符串输出时,又把x0设成了stdin,而且用了100的固定长度,输出内容完全不对。

修正后的代码

.data // 数据段开始
input:
    .space 100
inputSize = .-input
prompt:
    .asciz "Enter a string with 5 characters\n"
promptSize = .-prompt
reversed:
    .space 100
reversedSize = .-reversed
.text // 代码段开始
.global _start // Linux标准入口,类似C/C++的main
_start:
// 显示提示信息
mov x0, #1          // stdout文件描述符为1
ldr x1, =prompt     // 加载提示字符串地址
ldr x2, =promptSize // 加载提示字符串长度
mov x8, #64         // Linux write系统调用号
svc 0  

// 读取用户输入并保存字节数
mov x0, #0          // stdin文件描述符为0
ldr x1, =input      // 加载input缓冲区地址
ldr x2, =inputSize  // 最大读取字节数
mov x8, #63         // Linux read系统调用号
svc 0
mov x5, x0          // 把读取到的字节数存到x5,避免被覆盖

// 打印原输入(用于对比)
mov x0, #1          // stdout
ldr x1, =input      // input缓冲区地址
mov x2, x5          // 实际读取的字节数
mov x8, #64         // write系统调用
svc 0

// 反转字符串逻辑
ldr x1, =input      // x1指向input起始地址
sub x2, x1, #1      // 计算最后一个有效字符地址:起始地址-1 + 读取字节数
add x2, x2, x5
mov x4, #0          // 循环计数器,5字符需要交换2次(0<->4,1<->3)
loop: 
    cmp x4, #2
    b.gt end_loop   // 计数器大于2时退出循环

    ldrb w3, [x1]   // 读取左指针位置的字节
    ldrb w6, [x2]   // 读取右指针位置的字节(用w6避免覆盖计数器x4)
    
    strb w6, [x1]   // 把右字节写入左指针位置
    strb w3, [x2]   // 把左字节写入右指针位置
    
    add x1, x1, #1  // 左指针右移一位
    sub x2, x2, #1  // 右指针左移一位
    add x4, x4, #1  // 计数器加1
    b loop          
end_loop:

// 打印反转后的字符串
mov x0, #1          // stdout
ldr x1, =input      // 反转后的input缓冲区地址
mov x2, x5          // 实际读取的字节数
mov x8, #64         // write系统调用
svc 0

// 退出程序
mov x0, #0          // 返回值0
mov x8, #93         // exit系统调用号
svc 0   

关键修改点

  • 修正了文件描述符,确保输入输出方向正确;
  • 保存读取的字节数到x5,保证索引计算基于实际输入长度;
  • 让x1指向input缓冲区的真实地址,避免访问非法内存;
  • 用独立寄存器存储右字节,不再覆盖循环计数器;
  • 手动移动指针,逻辑更清晰,避免自动寻址带来的错误;
  • 输出时使用实际读取长度,避免输出多余空字符。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 03:24:59