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

Windows x64汇编中BSS段变量加减失效及初始值问题求助

修复Windows x64汇编简易银行系统的两个问题

问题原因分析与修复方案

1. money变量加减操作后数值无变化

错误出在choice_2和choice_3的金额计算逻辑:

  • 直接取withdraw_amount/deposit_amount的地址而非存储的数值(mov eax, withdraw_amount是取地址,正确应为mov eax, [withdraw_amount])
  • 未加载当前money的数值就进行加减操作,导致计算基于随机值而非实际余额

修复逻辑:

  • 先将当前money的值加载到寄存器
  • 读取输入的金额数值(而非地址)
  • 执行加减操作后写回money变量

2. 首次查看余额显示随机数值

BSS段的变量默认未初始化,money初始值为内存随机值。需要在程序启动时显式初始化money为0。

修复后的完整代码

default rel
bits 64

segment .data
    username                     db "saave",  0
    password                     db "root", 0

    information_text_username    db "please enter your username: ", 0 
    information_text_passw       db "please enter your password: ", 0
    
    not_equal                    db "username or password is incorrect", 0xa, 0

    entrance                     db "WELCOME TO SEA BANK", 0xa, 0
    option1                      db "1-Show Balance",      0xa, 0
    option2                      db "2-Withdraw Money",    0xa, 0
    option3                      db "3-Deposit Money",     0xa, 0
    option0                      db "exit",                0xa ,0
    ;option4                     db "calculate interest",  0xa

    userchoice0                  db "0", 0
    userchoice1                  db "1", 0
    userchoice2                  db "2", 0
    userchoice3                  db "3", 0
    ;userchoice4                 db "4", 0

    information_text_choice      db "Please choose your operation: ",          0
    information_text_userchoice1 db "Current balance: ",                       0
    information_text_userchoice2 db "Enter the amount you want to withdraw: ", 0
    information_text_userchoice3 db "Enter the amount you want to deposit: ",  0

    new_balance                  db "new balance: %d", 0xa, 0  ; 新增换行符,优化输出格式

    fmt_s                        db "%s", 0
    fmt_d                        db "%d", 0

segment .bss
    money:         resq 1       ; 用resq定义8字节变量,明确为64位整数
    user_name:     resb 8       ; 存储用户名
    pass_word:     resb 8       ; 存储密码
    choose:        resb 8       ; 存储用户选择
    withdraw_amount: resd 1     ; 用resd定义4字节整数,匹配%d输入类型
    deposit_amount: resd 1      ; 用resd定义4字节整数,匹配%d输入类型

segment .text

extern printf, scanf, strcmp, ExitProcess, _CRT_INIT

global main

exit:
    xor rax, rax
    call ExitProcess

hello_system:
    lea rcx, [option1]
    call printf
    mov rax, 0

    lea rcx, [option2]
    call printf
    mov rax, 0

    lea rcx, [option3]
    call printf
    mov rax, 0

    jmp user_choices

user_check:
    lea rcx, [information_text_username]
    call printf; 提示输入用户名
    mov rax, 0

    lea rcx, [fmt_s]
    mov rdx, user_name
    call scanf; 获取用户名
    mov rax, 0 

    lea rcx, [information_text_passw]
    call printf; 提示输入密码
    mov rax, 0

    lea rcx, [fmt_s]
    mov rdx, pass_word
    call scanf; 获取密码
    mov rax, 0

    lea rcx, [username]
    mov rdx, user_name
    call strcmp; 比较用户名

    test eax, eax
    jne not_equal_credentials; 不匹配则跳转
    
    lea rcx, [password] 
    mov rdx, pass_word
    call strcmp; 比较密码

    test eax, eax
    jne not_equal_credentials ; 不匹配则跳转

    lea rcx, [entrance] 
    call printf ; 输出欢迎信息
    mov rax, 0

    jmp hello_system

user_choices:
    lea rcx, [information_text_choice]
    call printf; 提示选择操作
    mov rax, 0

    lea rcx, [fmt_s]
    mov rdx, choose
    call scanf; 获取用户选择
    mov rax, 0

    lea rcx, [choose]
    mov rdx, userchoice1
    call strcmp
    
    test eax, eax
    je choice_1

    lea rcx, [choose]
    mov rdx, userchoice2
    call strcmp

    test eax, eax
    je choice_2

    lea rcx, [choose]
    mov rdx, userchoice3
    call strcmp

    test eax, eax
    je choice_3
    
    lea rcx, [choose]
    mov rdx, userchoice0
    call strcmp

    test eax, eax
    je exit

choice_1:
    lea rcx, information_text_userchoice1
    call printf
    mov rax, 0

    lea rcx, [fmt_d]
    mov rdx, [money]  ; 传递money的数值而非地址
    call printf; 打印余额
    mov rax, 0
    call printf       ; 打印换行,优化输出格式
    mov rax, 0

    jmp user_choices

choice_2:
    lea rcx, [information_text_userchoice2]
    call printf
    mov rax, 0

    lea rcx, [fmt_d]
    mov rdx, withdraw_amount
    call scanf
    mov rax, 0

    mov eax, [money]       ; 加载当前余额
    sub eax, [withdraw_amount] ; 减去取款金额
    mov [money], eax       ; 写回更新后的余额

    lea rcx, [new_balance]
    mov rdx, [money]       ; 传递更新后的余额数值
    call printf
    mov rax, 0

    jmp user_choices
    
choice_3:
    lea rcx, [information_text_userchoice3]
    call printf
    mov rax, 0

    lea rcx, [fmt_d]
    mov rdx, deposit_amount
    call scanf
    mov rax, 0

    mov eax, [money]       ; 加载当前余额
    add eax, [deposit_amount] ; 加上存款金额
    mov [money], eax       ; 写回更新后的余额

    lea rcx, [new_balance]
    mov rdx, [money]       ; 传递更新后的余额数值
    call printf
    mov rax, 0

    jmp user_choices

not_equal_credentials:
    lea rcx, [not_equal]
    call printf
    mov rax, 0
    jmp user_check

main:
    push rbp
    mov rbp, rsp
    sub rsp, 32

    mov qword [money], 0   ; 初始化余额为0,解决首次显示随机值问题
    
    jmp user_check

额外优化说明

  • 将money改为resq 1明确为64位整数,withdraw_amount和deposit_amount改为resd 1匹配%d的4字节输入,类型定义更清晰
  • 在new_balance格式字符串中添加换行符,输出排版更整洁
  • 修复choice_1中printf传递的参数为money的数值而非地址,避免错误输出内存地址

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 13:40:54