x86汇编罗马数字转换程序输出异常求助,曾遇main(void)错误
问题解决:x86汇编阿拉伯数字转罗马数字错误及main(void)错误成因
一、之前main(void)错误的成因
- 栈帧未初始化:Irvine32库的核心函数(如
WriteString、ReadInt)依赖规范的栈环境。如果main PROC开头未添加栈帧初始化代码(push ebp、mov ebp, esp),函数调用时会出现内存访问异常,错误会定位到第一条涉及库函数调用的指令(即mov edx, OFFSET msg1之后的call WriteString)。 - 数据段格式错误:最初
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
相关产品推荐
相关产品推荐

