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

x86汇编打印两数最大值异常及sys_write代码复用咨询

x86汇编程序问题:无法输出最大值结果 + 复用write代码块需求

问题说明

编写的x86汇编程序意图比较两个数a和b并输出最大值,但程序仅输出初始的"欢迎"消息,后续的结果消息无法输出。同时希望复用现有的write代码块来打印不同字符串,避免声明AMessage、BMessage这类独立变量。

现有代码(IsGreater.asm)

; 比较两个操作数A和B
; 若A > B则打印"YES"
; 若A < B则打印"NO"
; 若A == B则打印"EQUAL"

section .data;
    Message: db "Welcome to comparision program.", 10;
    MessageLength: equ $-Message;

    AMessage: db "Output: A is greater than B.", 10;
    AMessageLength: equ $-AMessage;

    BMessage: db "Output: B is greater than A.", 10;
    BMessageLength: equ $-BMessage;

section .bss;
    ; 动态变量
    a: resb 4;
    b: resb 5;

section .text;
    global _start;

; -----------------
write:
    mov eax, 4; sys_write
    mov ebx, 1; 文件描述符(标准输出)

    mov ecx, Message;
    mov edx, MessageLength;

    int 80h;  执行系统调用


exit:
    mov eax, 1; sys_exit
    mov ebx, 0; 设置无错误

    int 80h; 执行系统调用


printA:
    mov eax, 4; sys_write
    mov ebx, 1; 文件描述符(标准输出)

    mov ecx, AMessage;
    mov edx, AMessageLength;

    int 80h;  执行系统调用

printB:
    mov eax, 4; sys_write
    mov ebx, 1; 文件描述符(标准输出)

    mov ecx, BMessage;
    mov edx, BMessageLength;

    int 80h;  执行系统调用


_start:
    jmp write;

    ; mov word [a], 4;
    mov eax, [a];


    ; mov word [b], 5;
    mov ebx, [b];


    ; 比较a > b
    cmp eax, ebx;
    jg printA; 若a大于b则跳转
    jmp printB; 否则打印B的结果

    jmp exit;

当前输出

$ ./IsGreater
Welcome to comparision program.

预期输出

$ ./IsGreater
Welcome to comparision program.
Output: B is greater than A.

编译运行命令

# 编译命令
$ nasm IsGreater.asm -o IsGreater.o -f elf -F STABS -g
# 链接命令
$ ld IsGreater.o -o IsGreater -m elf_i386
# 运行命令
$ ./IsGreater

解决方案

1. 修复仅输出欢迎消息的问题

程序当前只输出欢迎消息的核心原因:

  • _start中使用jmp write跳转后,write代码块执行完会直接进入下方的exit代码段,触发程序退出,后续的比较逻辑完全没机会执行。
  • a和b变量未初始化,内存中是随机值,无法得到预期的比较结果。

修复步骤:

  • 将_start中的jmp write改为call write,利用call指令保存返回地址,write执行完后通过ret返回_start继续执行后续代码。
  • 在write代码块末尾添加ret指令,让执行流程回到调用处。
  • 取消a、b赋值代码的注释,给变量赋予明确值(比如a=4,b=5)。

2. 改造write代码块实现复用

要复用write打印不同字符串,采用寄存器传递参数的方式(32位Linux下常用约定):

  • 调用write前,将字符串地址存入ecx,长度存入edx。
  • 修改write代码块,移除硬编码的Message和MessageLength,直接使用传入的ecx和edx。
  • 移除冗余的printA、printB代码块,改为直接设置参数后调用write。

完整修改后的代码

; 比较两个操作数A和B
; 输出对应的最大值提示

section .data;
    Message: db "Welcome to comparision program.", 10;
    MessageLength: equ $-Message;

    AGreaterMsg: db "Output: A is greater than B.", 10;
    AGreaterLen: equ $-AGreaterMsg;

    BGreaterMsg: db "Output: B is greater than A.", 10;
    BGreaterLen: equ $-BGreaterMsg;

section .bss;
    ; 动态变量
    a: resb 4;
    b: resb 5;

section .text;
    global _start;

; -----------------
; 功能:打印字符串
; 参数:ecx=字符串地址,edx=字符串长度
write:
    mov eax, 4; sys_write
    mov ebx, 1; 文件描述符(标准输出)
    int 80h;  执行系统调用
    ret ; 返回调用处

exit:
    mov eax, 1; sys_exit
    mov ebx, 0; 设置无错误
    int 80h; 执行系统调用


_start:
    ; 打印欢迎消息
    mov ecx, Message
    mov edx, MessageLength
    call write

    ; 初始化变量a和b
    mov dword [a], 4
    mov dword [b], 5

    ; 加载变量值到寄存器
    mov eax, [a]
    mov ebx, [b]

    ; 比较a和b
    cmp eax, ebx
    jg printAGreater ; a大于b则跳转
    ; 否则打印b更大的消息
    mov ecx, BGreaterMsg
    mov edx, BGreaterLen
    call write
    jmp exit

printAGreater:
    mov ecx, AGreaterMsg
    mov edx, AGreaterLen
    call write
    jmp exit

验证

编译运行修改后的代码,会得到预期输出:

$ ./IsGreater
Welcome to comparision program.
Output: B is greater than A.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 16:30:12