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
相关产品推荐
相关产品推荐

