NASM汇编编程基础:初学者代码解读疑问咨询
解读NASM x86-64汇编代码:新手常见疑问解析
先把你的代码补全(补充常见的hextoascii实现,原代码未写完),方便后续分析:
%macro print 2 mov rax,1 mov rdi,1 mov rsi,%1 mov rdx,%2 syscall %endmacro %macro exit 0 mov rax,60 mov rdi,0 syscall %endmacro %macro accept 2 mov rax,0 mov rdi,0 mov rsi,%1 mov rdx,%2 syscall %endmacro section .data a dw 123AH section .bss b resb 2; buff resb 2; section .code global _start _start: accept b,2 mov rsi,a ;3 mov rbx,[rsi] ;6 call hextoascii mov rsi,buff ; 若要输出转换结果,需添加 print buff,2 exit hextoascii: ; 16位十六进制转ASCII的典型实现 mov ax, bx mov cx, 2 mov di, buff next: rol ax, 4 mov al, ah and al, 0Fh add al, 30h cmp al, 39h jbe store add al, 7h store: mov [di], al inc di dec cx jnz next ret
下面针对新手可能产生的疑问逐一拆解:
1. 这些print/exit/accept宏是什么?
这是NASM的自定义宏,用来把重复的系统调用代码打包成简洁的指令:
print:封装了x86-64的write系统调用(rax=1),参数1是输出缓冲区地址,参数2是输出长度,负责向标准输出(rdi=1)打印内容。exit:封装了exit系统调用(rax=60),用来退出程序并返回状态码0(rdi=0)。accept:封装了read系统调用(rax=0),从标准输入(rdi=0)读取指定长度的数据到目标缓冲区。
2. .data和.bss段有啥区别?
.data是已初始化数据段:这里的a dw 123AH是提前赋值好的变量,程序加载时就会把0x123A这个16位值写入内存,会占用可执行文件的存储空间。dw表示定义一个16位(Word)变量。.bss是未初始化数据段:b resb 2和buff resb 2是预留内存空间,程序启动时这些空间会被自动清零,不会占用可执行文件的额外空间,适合存储输入数据或临时计算结果。resb表示预留指定数量的字节。
3. mov rsi,a和mov rbx,[rsi]这两行做了什么?
mov rsi,a:把变量a的内存地址加载到rsi寄存器中。x86-64里rsi常被用作字符串/内存操作的源地址寄存器。mov rbx,[rsi]:从rsi指向的内存地址(也就是a的地址)读取数据到rbx。因为a是16位变量,所以实际读取的是0x123A,并自动零扩展到64位的rbx寄存器中(高48位补0)。其实更严谨的写法是mov bx,[rsi],直接操作16位寄存器,语义更清晰。
4. hextoascii函数的逻辑是什么?
这个函数的作用是把bx中存储的16位十六进制数,转换成对应的ASCII字符并存入buff缓冲区:
- 每次循环把
ax(这里把bx的值移到ax操作)循环左移4位,取出高4位的十六进制数字。 - 数字转ASCII:0-9直接加
0x30(对应字符'0'的ASCII值);A-F则额外加0x7(因为'A'的ASCII是0x41,0x3A+7=0x41)。 - 把转换后的字符写入
buff,移动缓冲区指针,循环2次(对应16位的两个十六进制字节)。
5. 代码里的潜在问题
accept b,2读取了2字节输入,但后续没有使用b的值,属于冗余代码,可能是你原本有其他逻辑没写完。- 原代码没有调用
print buff,2来输出转换后的ASCII结果,所以执行后看不到任何输出。 - 如果
hextoascii函数没有补全,程序会执行到未定义指令,直接崩溃。
内容的提问来源于stack exchange,提问作者asn
相关产品推荐
相关产品推荐

