NASM汇编实现十进制转二进制:除法存余数遇段错误求助
问题分析与修复
你的代码触发段错误主要有几个核心问题,逐个解决:
错误点1:字符串未转成整数就执行除法
dec_input是用户输入的十进制字符串(比如"123"),你直接把它的内存地址放到eax里执行div ebx,相当于用一个超大的地址数值做除法,完全不符合逻辑——必须先把字符串格式的十进制数转换为整数。
错误点2:余数未转成ASCII字符
div ebx得到的余数edx是数值0或1,直接存入binary_res的话,存储的是0x00或0x01(非打印字符),而且最终字符串没有以0h结尾,调用str_print时会越界访问内存,触发段错误。
错误点3:系统调用常量可能未定义
如果functions.asm里没定义SYS_READ(值为3)、STDIN(值为0),直接用这些符号会导致系统调用参数错误,引发异常。
修复后的完整代码
先补充字符串转整数的函数(可放入functions.asm)
; 字符串转整数:ebx=字符串地址,返回eax=整数数值 str_to_int: xor eax, eax ; 初始化结果为0 xor ecx, ecx str_to_int_loop: mov cl, [ebx] ; 取当前字符 cmp cl, 0h ; 遇到终止符结束 je str_to_int_end cmp cl, 0Ah ; 遇到输入时的换行符也结束 je str_to_int_end sub cl, '0' ; 字符转数值 imul eax, 10 ; 结果*10 add eax, ecx ; 加上当前位数值 inc ebx ; 移动到下一个字符 jmp str_to_int_loop str_to_int_end: ret
主程序修正
%include 'functions.asm' section .data ip_prompt db "Enter a decimal number to be converted to binary: ", 0h binary_res db 32 dup('0'), 0h ; 提前加字符串终止符,避免越界 section .bss dec_input resb 32 section .text global _start _start: mov eax, ip_prompt call str_print ; 直接用数值调用系统读取,避免常量未定义问题 mov eax, 3 ; SYS_READ mov ebx, 0 ; STDIN mov ecx, dec_input mov edx, 32 int 80h mov eax, dec_input call str_print ; 将输入的字符串转为整数 mov ebx, dec_input call str_to_int mov ecx, 0 mov ebx, 2 convert_to_bin: xor edx, edx ; 每次div前必须清零edx,避免旧余数干扰 div ebx add dl, '0' ; 把余数转成ASCII字符(取edx低8位操作) mov [binary_res + ecx], dl inc ecx cmp eax, 0 jne convert_to_bin ; 可选:反转字符串得到正常顺序的二进制(当前存储的是逆序,余数先存最低位) mov eax, binary_res mov edx, ecx ; ecx是二进制位数,传入反转函数 call reverse_str mov eax, binary_res call str_print_endl call quit
可选:添加字符串反转函数(得到高位在前的二进制)
如果需要输出正常顺序的二进制,补充反转函数到functions.asm:
; 反转字符串:eax=字符串地址,edx=字符串长度 reverse_str: push ebx push esi push edi mov esi, eax mov edi, eax add edi, edx dec edi ; edi指向最后一个有效字符 reverse_loop: cmp esi, edi jge reverse_end mov bl, [esi] mov cl, [edi] mov [esi], cl mov [edi], bl inc esi dec edi jmp reverse_loop reverse_end: pop edi pop esi pop ebx ret
内容的提问来源于stack exchange,提问作者ciao
相关产品推荐
相关产品推荐

