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

NASM汇编终端参数获取异常:传入Aa无预期输出的排查与修复

问题分析与修复:NASM汇编命令行参数处理错误

问题描述

我编写的NASM汇编逻辑为:接收一个由两个ASCII字符组成的命令行参数(例如Aa),交换该参数的两个字符得到aA,将其与十六进制值0x6141(对应aA的ASCII编码)比较,若相等则打印预设的Hit信息。但执行./program Aa时无任何预期输出,求问题原因及修复方法。

原汇编代码

section .data
    NULL equ 0
    EXIT_SUCCESS equ 0
    SYS_exit equ 60

    hit db "Hit! a etiqueta ja se encontra preenchida", 0xA  
    hit_len equ $ - hit 

section .text
global _start
_start:
    
    mov rdi, [rsp]        
    lea rsi, [rsp + 8]    

    cmp rdi, 1           
    jle _done

    
    mov rbx, [rsi]       
    mov rbx, [rsi + 8]    
    xchg bl, bh
    
    cmp rbx, 0x6141
    jne _done
   
_print_Hit:

    xor rax, rax
    mov rax, 1           
    mov rdi, 1           
    mov rsi, hit     
    mov rdx, hit_len 
    syscall

_done:
    ; Finalizar programa
    mov rax, SYS_exit
    mov rdi, EXIT_SUCCESS
    syscall

编译运行命令

┌──(mattandmello㉿MattandMello)-[~/Desktop]
└─$ nasm -f elf64 -g -F dwarf program.asm                                                
                                                                                                            
┌──(mattandmello㉿MattandMello)-[~/Desktop]
└─$ gcc program.o biblioteca.o -o program -nostartfiles -fPIE -no-pie -lncurses
/usr/bin/ld: warning: validationBitSiml.o: missing .note.GNU-stack section implies executable stack
/usr/bin/ld: NOTE: This behaviour is deprecated and will be removed in a future version of the linker
                                                                                                            
┌──(mattandmello㉿MattandMello)-[~/Desktop]
└─$ ./program Aa                                                                         

问题原因

  1. 参数内容读取错误:原代码中mov rbx, [rsi + 8]获取的是argv[1]的指针(字符串的内存地址),而非字符串的实际字符内容,后续交换和比较操作都是基于无效的地址值进行的。
  2. 冗余无效指令:mov rbx, [rsi]指令被下一行立即覆盖,无任何实际作用,属于冗余代码。
  3. 字节序与比较值不匹配:x86_64架构采用小端序存储,输入Aa的内存布局为低地址存0x41('A')、高地址存0x61('a'),交换后得到的aA对应的16位值为0x4161(小端序),但原代码错误地与大端序的0x6141比较,导致判断失败。

修复方案

  1. 通过argv[1]的指针读取字符串的前两个字节到寄存器,而非直接使用指针地址。
  2. 移除冗余的mov rbx, [rsi]指令。
  3. 将比较目标值改为小端序对应的0x4161,匹配交换后的实际值。

修复后的代码

section .data
    NULL equ 0
    EXIT_SUCCESS equ 0
    SYS_exit equ 60

    hit db "Hit! a etiqueta ja se encontra preenchida", 0xA  
    hit_len equ $ - hit 

section .text
global _start
_start:
    ; 获取参数个数argc
    mov rdi, [rsp]        
    ; 获取argv数组起始地址
    lea rsi, [rsp + 8]    

    ; 检查是否存在至少一个命令行参数(argc >= 2)
    cmp rdi, 2           
    jl _done

    ; 获取argv[1]的指针(输入参数的字符串地址)
    mov rbx, [rsi + 8]    
    ; 读取字符串的前两个字节到bx(小端序)
    mov bx, [rbx]
    ; 交换两个字符的字节
    xchg bl, bh
    
    ; 交换后"aA"对应的小端序16位值是0x4161
    cmp bx, 0x4161
    jne _done
   
_print_Hit:
    mov rax, 1           ; sys_write系统调用号
    mov rdi, 1           ; 标准输出文件描述符
    mov rsi, hit         ; 要打印的字符串地址
    mov rdx, hit_len     ; 字符串长度
    syscall

_done:
    ; 退出程序
    mov rax, SYS_exit
    mov rdi, EXIT_SUCCESS
    syscall

验证

使用原编译命令重新编译运行,执行./program Aa即可正常输出预设的Hit信息。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 03:15:05