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

x86汇编罗马数字转换程序输出异常求助,曾遇main(void)错误

问题解决:x86汇编阿拉伯数字转罗马数字错误及main(void)错误成因

一、之前main(void)错误的成因

  1. 栈帧未初始化:Irvine32库的核心函数(如WriteString、ReadInt)依赖规范的栈环境。如果main PROC开头未添加栈帧初始化代码(push ebp、mov ebp, esp),函数调用时会出现内存访问异常,错误会定位到第一条涉及库函数调用的指令(即mov edx, OFFSET msg1之后的call WriteString)。
  2. 数据段格式错误:最初roman数组的写法(如"M\0\0")不符合汇编字符串定义规范,导致后续变量(如msg1)的内存偏移计算错误,访问时触发异常,修正数据段后该问题消失。

二、罗马数字输出错误的解决方案

你的代码存在3个核心错误,逐一修正即可:

1. 修正罗马数字字符串的存储方式

原代码中roman数组用连续字节存储字符串,无法正确索引多字符的罗马符号(如"CM")。应改为指针数组,每个元素指向独立的罗马字符串:

.data
    arabic DWORD 1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1
    ; 指针数组,每个元素对应阿拉伯数字的罗马字符串指针
    roman DWORD OFFSET M, OFFSET CM, OFFSET D, OFFSET CD, OFFSET C, OFFSET XC, OFFSET L, OFFSET XL, OFFSET X, OFFSET IX, OFFSET V, OFFSET IV, OFFSET I
    ; 定义各个罗马字符串,均以0结尾(符合Irvine32的WriteString要求)
    M BYTE "M", 0
    CM BYTE "CM", 0
    D BYTE "D", 0
    CD BYTE "CD", 0
    C BYTE "C", 0
    XC BYTE "XC", 0
    L BYTE "L", 0
    XL BYTE "XL", 0
    X BYTE "X", 0
    IX BYTE "IX", 0
    V BYTE "V", 0
    IV BYTE "IV", 0
    I BYTE "I", 0
    N DWORD 0
    msg1 BYTE 'Enter arabic number:', 0
    msg2 BYTE 0Dh, 0Ah, 'Roman number:', 0  ; 用0Dh,0Ah代替\n,汇编中直接写\n可能不识别

2. 修正循环退出条件

原代码中cmp esi, 12会导致最后一个元素(数值1)无法被处理,因为数组共有13个元素(索引0-12),应改为:

convert_loop:
    cmp esi, 13        ; 当esi等于13时退出循环(所有元素处理完毕)
    jge exit_loop

3. 修正罗马数字打印与数值减法逻辑

原代码错误地将罗马字符的ASCII值作为减法数值,且只打印单个字符。应改为打印完整字符串,并使用阿拉伯数字数组中的对应值做减法:

convert_loop:
    cmp esi, 13
    jge exit_loop

    ; 取出当前阿拉伯数字值
    mov eax, [arabic + esi * 4]
    cmp N, eax
    jl increment_index

    ; 保存当前阿拉伯数字值到ebx(避免被后续指令覆盖)
    mov ebx, eax
    ; 取出对应罗马字符串的指针并打印
    mov edx, [roman + esi * 4]
    call WriteString
    ; 减去对应阿拉伯数字值
    sub N, ebx
    jmp convert_loop

increment_index:
    add esi, 1
    jmp convert_loop

完整修正后的代码

INCLUDE irvine32.inc
includelib irvine32.lib

.data
    arabic DWORD 1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1
    roman DWORD OFFSET M, OFFSET CM, OFFSET D, OFFSET CD, OFFSET C, OFFSET XC, OFFSET L, OFFSET XL, OFFSET X, OFFSET IX, OFFSET V, OFFSET IV, OFFSET I
    M BYTE "M", 0
    CM BYTE "CM", 0
    D BYTE "D", 0
    CD BYTE "CD", 0
    C BYTE "C", 0
    XC BYTE "XC", 0
    L BYTE "L", 0
    XL BYTE "XL", 0
    X BYTE "X", 0
    IX BYTE "IX", 0
    V BYTE "V", 0
    IV BYTE "IV", 0
    I BYTE "I", 0
    N DWORD 0
    msg1 BYTE 'Enter arabic number:', 0
    msg2 BYTE 0Dh, 0Ah, 'Roman number:', 0

.code
main PROC
    push ebp
    mov ebp, esp

    ; 打印输入提示
    mov edx, OFFSET msg1
    call WriteString

    ; 读取输入到N
    call ReadInt
    mov N, eax

    ; 打印结果提示
    mov edx, OFFSET msg2
    call WriteString

    mov esi, 0

convert_loop:
    cmp esi, 13
    jge exit_loop

    mov eax, [arabic + esi * 4]
    cmp N, eax
    jl increment_index

    mov ebx, eax
    mov edx, [roman + esi * 4]
    call WriteString
    sub N, ebx
    jmp convert_loop

increment_index:
    add esi, 1
    jmp convert_loop

exit_loop:
    pop ebp
    invoke ExitProcess, 0

main ENDP
END main

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 03:01:02