x86汇编中十六进制转ASCII的代码逻辑疑问求助
解析64位x86汇编:十六进制转ASCII并显示的代码片段
咱们一步一步拆解这段代码,搞清楚它到底在做什么,以及每一步操作的原因:
核心功能
这段代码的作用是把一个64位整数(默认存放在rax寄存器中)转换成16个十六进制字符的ASCII码,存入char_answer数组后调用显示函数输出。因为64位刚好对应16个十六进制数字(每4位一个),所以循环执行16次。
逐行代码解析
初始化部分
mov rsi,char_answer+15 mov rcx,16
mov rsi,char_answer+15:char_answer是一个16字节的数组,这里把rsi(源变址寄存器)指向数组的最后一个元素。因为我们要从整数的最低位十六进制数字开始转换,然后往前存储,这样最终数组里的内容就是从高位到低位的正常十六进制字符串顺序。mov rcx,16:设置循环计数器为16,对应64位整数的16个十六进制位,确保我们会转换每一位数字。
循环体(cnt标签开始)
cnt: mov rdx,0 mov rbx,16h div rbx
mov rdx,0:在64位模式下,div指令的被除数是rdx:rax(rdx存高位,rax存低位)。这里清零rdx是为了避免之前的残留数据影响除法结果,保证我们只对rax里的目标整数做除法。mov rbx,16h:这里应该是笔误,正确的十六进制除数应该是10h(十进制16),这样余数才会是0-15,刚好对应十六进制的0-F。div rbx:执行除法,rax除以rbx,商存回rax(相当于把整数右移4位,去掉已经处理的最低位),余数存在rdx(当前要转换的十六进制数字存在dl,即rdx的低8位)。
十六进制转ASCII逻辑
cmp dl,09h jbe add30 add dl,07h add30: add dl,30h
这部分是核心的转换步骤:
cmp dl,09h:判断当前余数(十六进制数字)是0-9还是A-F(10-15)。jbe add30:如果余数小于等于9,直接跳转到add30标签,转换成对应的ASCII数字。add dl,07h:如果余数大于9(对应A-F),先加07h——因为ASCII里'9'是39h,'A'是41h,中间差了7,加上这个偏移量才能让10-15转换成正确的字母ASCII码。add dl,30h:把余数转换成ASCII码:0-9加30h得到'0'-'9',10-15经过前面加07h后再加30h,刚好得到'A'-'F'。
存储结果与循环控制
mov [rsi],dl dec rsi dec rcx jnz cnt
mov [rsi],dl:把转换好的ASCII字符存入rsi指向的数组位置。dec rsi:rsi减1,指向下一个(更靠前的)数组元素,准备存储下一个更高位的十六进制数字。dec rcx:循环计数器减1。jnz cnt:如果计数器不为0,跳回cnt标签继续循环,直到16位全部转换完成。
显示与返回
scall 1,1,char_answer,16 ret
scall 1,1,char_answer,16:调用自定义的显示函数(或者系统调用),参数应该是:显示位置(行1,列1)、要显示的缓冲区char_answer、显示长度16,把数组里的十六进制字符串输出。ret:从这个显示过程返回。
内容的提问来源于stack exchange,提问作者Arinjay Gholap




