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

32位GAS格式汇编:命令行输入转整数及相加输出实现问题

问题描述

我有一个用GCC编译的程序,能接收命令行参数并打印到屏幕,栈中存储着指向输入参数的地址。现在需要把前两个命令行参数转换成整数,相加后输出结果,但尝试了几种方法都失败了:

  • 通过寄存器解引用相加(代码:movl (%edi), %edi; addl %edi, (%esi))
  • 减去"0"实现字符串转整数(代码:sub "0", (%esi))
  • 将第二个参数存入%edx后相加

附上部分汇编代码:

printLoop:
    movl    12(%ebp), %esi          # Get **argv pointer to the vector table
    movl    (%esi,%ebx,4), %esi     # Use the pointer to indirectly load the address of the
                                    # next command line argument. %ebx is the index
    incl    %ebx    
    movl    12(%ebp), %edi                       
    movl (%edi, %ebx, 4), %edi      #pointer to next arg in edi?
    
    #sub "0", (%esi) 
    
    movl (%edi), %edi    # don't work
    addl %edi, (%esi)    # don't work
      

    call    printString             # print the null terminated command line argument

    movl    $newLine, %esi          # go to the next line
    call    printString             # prints the arg
解决思路与代码修正

你的核心问题是没正确处理字符串到整数的转换——命令行参数是ASCII字符串,不是直接的二进制整数,不能直接解引用寄存器取数值相加。下面分步骤解决:

1. 实现字符串转整数的函数

先写一个处理正整数转换的汇编函数(需要支持负数可自行扩展):

; 输入:%esi = 指向以null结尾的数字字符串的指针
; 输出:%eax = 转换后的整数
str_to_int:
    pushl %ebx
    pushl %ecx
    pushl %edx
    movl $0, %eax          ; 初始化结果为0
str_loop:
    movb (%esi), %bl       ; 取当前字符
    cmpb $0, %bl           ; 判断是否到字符串末尾
    je str_done
    subb $'0', %bl         ; 转成数字(ASCII码减'0'的ASCII值)
    imull $10, %eax        ; 结果乘10
    addl %ebx, %eax        ; 加上当前数字
    incl %esi              ; 指针移到下一个字符
    jmp str_loop
str_done:
    popl %edx
    popl %ecx
    popl %ebx
    ret

2. 正确获取并转换前两个参数

不要用原代码的循环逻辑(原逻辑会遍历所有参数),直接定位argv[1]和argv[2]进行处理:

; 以GCC编译的main函数为例
main:
    pushl %ebp
    movl %esp, %ebp

    ; 检查参数数量是否足够(至少需要2个数字参数,argc >=3)
    movl 8(%ebp), %eax
    cmpl $3, %eax
    jl exit_error          ; 参数不够则退出

    ; 转换第一个参数argv[1]
    movl 12(%ebp), %esi
    movl 4(%esi), %esi     ; 取argv[1]的地址
    call str_to_int
    movl %eax, %ebx        ; 暂存第一个整数到%ebx

    ; 转换第二个参数argv[2]
    movl 12(%ebp), %esi
    movl 8(%esi), %esi     ; 取argv[2]的地址
    call str_to_int

    ; 两个整数相加,结果存在%eax
    addl %ebx, %eax

    ; 将结果转成字符串并打印(假设已有int_to_str和printString函数)
    pushl %eax
    call int_to_str
    call printString
    movl $newLine, %esi
    call printString

    ; 正常退出
    movl $0, %eax
    leave
    ret

exit_error:
    ; 打印参数不足的错误信息
    movl $error_msg, %esi
    call printString
    movl $1, %eax          ; 退出码设为1
    leave
    ret

; 定义常量
newLine: .asciz "\n"
error_msg: .asciz "需要至少两个数字参数\n"

3. 原代码的错误点说明

  • movl (%edi), %edi:这是取argv[n]指向的字符串的前4字节(比如字符串"123"会取0x33323100,并非整数123),逻辑完全错误。
  • sub "0", (%esi):语法错误,AT&T汇编中立即数需加$,应为subb $'0', (%esi),且该操作仅修改字符串第一个字符,未处理多位数,也未将结果存入寄存器用于计算。
  • 直接相加寄存器解引用的值:本质是对字符串的二进制内容做加法,而非整数运算,结果必然错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 21:33:27