16位BIOS模式下AT&T汇编:磁盘扇区内容循环打印指令选择咨询
16位BIOS模式下遍历磁盘扇区并打印十六进制值的汇编实现
背景
已通过AT&T汇编实现read_sector函数,利用0x13中断的索引寻址方式将单个磁盘扇区加载到内存地址0xD000起始位置。现需遍历该扇区的所有字节,调用已实现的cons_write_hex函数打印每个字节的十六进制值,可用cx寄存器作为循环计数器,纠结使用jmp还是loop指令实现循环。
现有代码
read_sector: movw $disk_address_packet, %si movw $1, 2(%si) movw $0xD000, 4(%si) movw $1, 8(%si) movb $0x42, %ah movb (boot_device), %dl int $0x13 jc read_failed movb (0xD000), %al # 检查扇区是否为空 cmpb $0, %al je read_failed cons_write_hex: movw $4, %cx movb $0x0E, %ah hexloop: rol $4, %bx # 左移4位 movw %bx, %si and $0x000F, %si movb HexChars(%si), %al int $0x10 loop hexloop ret
解决方案:使用loop指令实现循环
为什么选loop而非jmp
loop是x86架构专为计数循环设计的指令,它会自动完成**cx减1和判断是否为0**的操作:若cx减1后不为0,则跳转到指定标签;若为0则继续执行后续代码。相比手动用jmp实现(需单独写dec %cx、cmp $0, %cx、jnz指令),loop代码更简洁、可读性更强,完全适配用cx做计数器的场景。
遍历扇区并打印的实现代码
; 遍历0xD000起始的扇区,打印每个字节的十六进制值 print_sector: movw $512, %cx ; 单个磁盘扇区默认512字节,设置循环计数器 movw $0xD000, %si ; 指向扇区的起始内存地址 print_loop: pushw %cx ; 保存主循环的计数器值(cons_write_hex会修改cx) movzbw (%si), %bx ; 取出当前字节,零扩展为16位存入bx(cons_write_hex依赖bx传参) call cons_write_hex ; 调用打印函数 popw %cx ; 恢复主循环的计数器 incw %si ; 指针移动到下一个字节 loop print_loop ; cx减1,不为0则继续循环 ret
关键注意点
cons_write_hex函数内部会修改cx寄存器(将其设为4用于自身的打印循环),因此在调用前必须用pushw %cx保存主循环的计数器值,调用后用popw %cx恢复,避免主循环计数出错。- 使用
movzbw指令将8位字节零扩展为16位存入bx,确保cons_write_hex处理的是完整的16位寄存器值,避免符号扩展导致的打印错误。
内容的提问来源于stack exchange,提问作者CharlesTheZouch
相关产品推荐
相关产品推荐

