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

Linux下x86-64汇编中如何正确通过参数传递数据?

问题:x86-64 Linux汇编中无法正确获取命令行参数

我在x86-64 Linux汇编程序中尝试通过命令行参数获取文件名和整数,但加载参数到寄存器时得不到预期结果。以下是我的代码和相关信息:

Makefile

AS = /usr/bin/nasm
LD = /usr/bin/ld

ASFLAGS = -g -f elf64
LDFLAGS = -static

SRCS = lab.s
OBJS = $(SRCS:.s=.o)

EXE = lab

all: $(SRCS) $(EXE)

clean:
        rm -rf $(EXE) $(OBJS)

$(EXE): $(OBJS)
        $(LD) $(LDFLAGS) $(OBJS) -o $@

.s.o:
        $(AS) $(ASFLAGS) $< -o $@

lab.s 汇编代码

bits    64
;       Print text file
global  _start
_start:
        cmp     dword [rsp], 3

        mov     rax, [rsp]
        mov     rdx, [rsp + 8]
        mov     rbx, [rsp + 16]
        mov     rsi, [rsp + 24]
        mov     rsi, [rsi]

        mov     eax, 1          ; write
        mov     edi, 1          ; standart_output
        mov     rsi, [rsp + 16] ; name
        xor     edx, edx        ; size = 0 ->

find_size:
        cmp     byte [rsi+rdx], 0
        je      print
        inc     edx
        jmp     find_size

print:
        syscall

        mov     edi, 1
        mov     eax, 60
        syscall

调试信息

  1. 参数地址:栈中rsp指向的参数个数为3,后续依次是程序名、文件名参数、整数参数的内存地址。
  2. 数值获取异常:尝试加载整数参数值时,寄存器中未能得到预期的整数值。

问题分析与解决

核心问题

  1. 对命令行参数结构理解错误:x86-64 Linux下,rsp初始指向命令行参数个数(argc),后续每个8字节是参数的字符串指针,而非参数的直接数值。你用mov rsi, [rsi]试图获取整数值,实际只是取了字符串首地址指向的8字节原始数据,并非字符串转整数后的结果。
  2. 缺少参数合法性检查分支:代码开头cmp dword [rsp], 3后没有处理参数个数不符的情况,会导致后续非法栈访问。
  3. 寄存器使用不符合规范:rbx是Linux系统调用的保留寄存器,随意使用可能破坏程序上下文。

修复方案

  1. 添加参数检查逻辑:参数个数不等于3时直接退出,避免非法操作:
    cmp     dword [rsp], 3
    jne     exit_fail
    
  2. 实现字符串转整数逻辑:命令行参数都是字符串形式,必须手动转换为整数(类似C语言的atoi函数)。
  3. 规范寄存器使用:改用非保留寄存器存储临时数据,比如rcx。

修复后的示例代码

bits    64
global  _start

_start:
        ; 检查参数个数是否为3
        cmp     dword [rsp], 3
        jne     exit_fail

        ; 提取参数指针:[rsp+16]是文件名,[rsp+24]是整数字符串
        mov     rdi, [rsp + 16]
        mov     rsi, [rsp + 24]

        ; 打印文件名
        mov     eax, 1
        mov     rdx, 0
find_size:
        cmp     byte [rdi + rdx], 0
        je      print_name
        inc     rdx
        jmp     find_size
print_name:
        syscall

        ; 将整数字符串转换为整数,结果存在rax中
        xor     rax, rax
atoi_loop:
        movzx   rcx, byte [rsi]
        test    rcx, rcx
        je      atoi_done
        sub     rcx, '0'
        imul    rax, 10
        add     rax, rcx
        inc     rsi
        jmp     atoi_loop
atoi_done:
        ; 此处可使用rax中的整数进行后续操作

        ; 正常退出
        mov     eax, 60
        xor     edi, edi
        syscall

exit_fail:
        mov     eax, 60
        mov     edi, 1
        syscall

关键提示

  • 所有命令行参数均为ASCII字符串,必须通过字符串转整数逻辑才能得到数值类型的参数值。
  • 遵守x86-64 Linux系统调用的寄存器约定:rax存储系统调用号,rdi/rsi/rdx传递参数,rbx/rbp/r12-r15为保留寄存器,使用前需保存上下文(如需恢复)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 04:35:09