Linux下NASM汇编如何用printf打印递减十六进制数字水平列表
解决方案:用汇编实现循环输出十六进制递减序列(无write系统调用)
既然不能直接硬编码输出字符串,也无法使用write系统调用,我们可以通过循环遍历+十六进制转ASCII+DOS/BIOS中断输出的方式实现需求。以下是具体的x86汇编实现(NASM语法,DOS实模式):
org 0x100 ; COM程序起始地址 start: mov cx, 0xF ; 初始化循环计数器为十六进制F(十进制15) loop_start: mov ax, cx ; 将当前计数器值传入ax用于ASCII转换 call hex_to_ascii ; 调用转换子程序,结果存入dl寄存器 call print_char ; 输出转换后的字符 cmp cx, 0 ; 判断当前是否为最后一个数字(0) je skip_space ; 若是0则跳过空格输出 mov dl, 0x20 ; 空格的ASCII码 call print_char skip_space: dec cx ; 计数器递减 jge loop_start ; 只要计数器≥0,继续循环 mov ah, 0x4C ; DOS程序退出功能 int 0x21 ; 子程序:将ax中0-15的数值转为十六进制ASCII字符,结果存在dl hex_to_ascii: cmp ax, 9 jle is_digit ; 数值≤9,转为0-9的ASCII add ax, 0x37 ; 数值≥10,转为A-F的ASCII(0xA+0x37=0x41='A') jmp convert_done is_digit: add ax, 0x30 ; 转为0-9的ASCII(0+0x30=0x30='0') convert_done: mov dl, al ret ; 子程序:输出dl中的ASCII字符(使用DOS中断0x21的0x02功能) print_char: mov ah, 0x02 int 0x21 ret
核心逻辑说明
- 循环控制:用
cx寄存器作为循环计数器,从0xF开始递减,通过dec cx和jge loop_start实现循环,直到计数器变为-1时退出。 - 十六进制转ASCII:通过判断数值大小,分别加上
0x30(数字)或0x37(字母)完成转换,完全避免硬编码字符串。 - 字符输出:使用DOS中断
int 21h的0x02功能输出单个字符,而非write系统调用,符合需求。 - 格式控制:每次输出字符后判断是否为0,若非0则输出空格,保证最终输出格式为
F E D C B A 9 8 7 6 5 4 3 2 1 0。
如果需要脱离DOS环境,可改用BIOS视频中断替换输出子程序:
; 替换后的print_char子程序(BIOS实模式输出) print_char: mov ah, 0x0E mov bh, 0x00 ; 显示页码 mov bl, 0x07 ; 文本属性(黑底白字) int 0x10 ret
内容的提问来源于stack exchange,提问作者Psiodyne8
相关产品推荐
相关产品推荐

