使用NASM编写两数相加汇编程序结果异常,寻求排查方向
作为汇编新手遇到这种问题太正常了——NASM里哪怕一个寄存器用错、ASCII转换漏一步,结果都会完全跑偏。你输出固定是'j',大概率是数值和ASCII码的转换环节出了问题,或者结果的存储/读取逻辑有bug。咱们一步步来排查:
先查输入的ASCII转数值环节
你输入的数字(比如"5")本质是ASCII码0x35,如果直接把这个值拿去相加,得到的结果还是ASCII码范围的数。比如两个"5"相加是0x35+0x35=0x6A,刚好是字符'j'的ASCII码——这完全符合你遇到的情况!所以要确认:读取输入后有没有用sub al, '0'把ASCII字符转成对应的十进制数值?比如:; 假设你读取了第一个字符到num1变量 mov al, [num1] sub al, '0' ; 这一步把'5'转成数值5,必须要有! mov [num1_val], al再检查输出的数值转ASCII环节
相加得到的是十进制数值(比如10),不能直接输出这个数值——直接输出10的话是换行符,输出106就是'j'。你需要把数值转回ASCII字符:用add al, '0'把数值转成对应的字符,比如数值8转成'8'(0x38)。如果结果是两位数(比如12),还要拆分个位和十位,分别转成ASCII后再按顺序输出。排查寄存器/内存的错误使用
有没有可能相加后的结果被后续的操作覆盖了?比如你把结果存在al里,但后面调用输出系统调用(int 0x80)时,eax被设置成了4(输出的系统调用号),导致原来的结果丢失?这时候需要把结果先存在内存变量里,或者用其他寄存器保存(比如push到栈里)。用调试工具定位问题
新手一定要学会用gdb调试!编译的时候加上-g参数(nasm -f elf32 -g add.asm -o add.o),然后用gdb ./add启动调试:- 用
break _start设置断点,然后run开始执行 - 每一步用
nexti单步执行,用info registers看寄存器的值,用x /b &sum看内存里的结果
这样你能清楚看到输入转数值对不对、相加结果对不对、转ASCII后的值是不是正确的。
- 用
检查编译链接参数
确保你用的是和代码匹配的位数,比如32位代码用nasm -f elf32,链接用ld -m elf_i386,如果位数不匹配,可能会出现奇怪的运行错误。
小提示:可以先写极简版的代码——比如先读取一个数字,转成数值,直接转ASCII输出,确认这一步没问题,再加上第二个数字和相加逻辑,逐步验证,这样更容易找到问题。
内容的提问来源于stack exchange,提问作者raka

