这是我第一次真正发帖提问。如果有一些我不遵守的格式/习俗,我很抱歉,如果是这样,请告诉我。
我在OS类的介绍中,我们应该编写一个bootloader。分配的一部分是使用INT 0x10中断向终端输出一个数字。例如,我想将某个寄存器中十六进制数0xFFF表示的字节数打印到其十进制等效值4095.首先,我编写汇编只是将存储值输出到其十进制等值:
.globl main
.code16
main:
movw $0x9000, %ax
movw %ax, %ss
xorw %sp, %sp
movw $0x0003, %ax
int $0x10
movw $0, %ax
movw %ax, %ds
movw %ax, %es
mov $0xfff, %eax # test value, decimal rep is 4095
mov $0, %bl
call div10
div10:
mov $10, %ecx # divisor
mov $0, %edx # set register to 0 - will store remainder
div %ecx
push %eax # push result to stack
mov %dl, %al # move remainder value to %al for output
add $0x30, %al # add '0' to value to attain ascii equiv
mov $0x0E, %ah
int $0x10 # INT 0x10 instruction to print to terminal
pop %eax # pop test value back to eax reg
cmp $0, %eax # if eax is 0, conversion is complete
je return
call div10
return:
这段代码的输出是5904
,考虑到我以相反的顺序输出,这是有道理的。我试着按正确的顺序输出数字到堆栈,然后用计数器弹出:
.globl main
.code16
main:
movw $0x9000, %ax
movw %ax, %ss
xorw %sp, %sp
movw $0x0003, %ax
int $0x10
movw $0, %ax
movw %ax, %ds
movw %ax, %es
mov $0xfff, %eax # test value
mov $0, %bl
call div10
div10:
mov $10, %ecx # divisor
mov $0, %edx # set register to 0 - will store remainder
div %ecx
push %dx # push digit onto stack
add $1, %bl # counter for number of digits - inc by 1
cmp $0, %eax # if eax is 0, conversion is complete
je print_bytes
call div10
print_bytes:
sub $1, %bl # counter decremented till 0
mov $0, %ecx # set registers to 0
mov $0, %eax
pop %cx # pop digit value to %cx register
mov %cl, %al # move to %al to be output
add $0x30, %al # add '0' char to convert to ascii equivalent
mov $0x0E, %ah
int $0x10 # interrupt to print to screen
cmp $0, %bl
je return
call print_bytes
return:
对于给定的测试值(0xFFF,转换为4095十进制),它输出'4ééé'。它似乎正确输出第一个数字,然后无法正确输出剩余的数字。我究竟做错了什么?我觉得在弹出我的价值观时会发生一些事情。
我现在才学习汇编(通常使用Java,C ++等高级语言),所以我确信编码实践有问题。请指出这些给我!我感谢任何/所有反馈。
编辑:修正了问题。 @Jester建议不使用call div10
似乎解决了这个问题。我很感激帮助!