Assembly Hello World引导加载程序在第一个字符后挂起
我将此代码用于Hello world引导加载程序。它不打印“Hello world\n”,只打印“H”并挂起。我已经使用loadsb成功地打印了消息,但我不明白为什么这种方法不起作用,因为它看起来是等效的Assembly Hello World引导加载程序在第一个字符后挂起,assembly,operating-system,x86,bootloader,Assembly,Operating System,X86,Bootloader,我将此代码用于Hello world引导加载程序。它不打印“Hello world\n”,只打印“H”并挂起。我已经使用loadsb成功地打印了消息,但我不明白为什么这种方法不起作用,因为它看起来是等效的 [ORG 0x7c00] [BITS 16] xor ax, ax ;make it zero mov ds, ax mov ecx, msg bios_print: mov al, [ecx] add ecx,1 cmp al, 0 ;
[ORG 0x7c00]
[BITS 16]
xor ax, ax ;make it zero
mov ds, ax
mov ecx, msg
bios_print:
mov al, [ecx]
add ecx,1
cmp al, 0 ;zero=end of str
je hang ;get out
cmp al,100
jge hang
mov ah, 0x0E
int 0x10
jmp bios_print
hang:
jmp hang
msg db 'Hello World', 13, 10, 0
times 510-($-$$) db 0
db 0x55
db 0xAA
编辑:
我将[BITS 64]更改为[BITS 16]您的程序正以您编码的方式工作。ASCII中的小写字母
e
表示为65h
,在十进制中等于101。因此,如果e
(101)处于al
中,则执行cmp al,100/jge hang
将导致跳转到标签hang
。一切都很好
您的问题的一个解决方案是简单地删除该行,因为我看不出它有什么用途-看看您是如何让字符串以\0
结尾的,循环将在到达末尾时结束
不过,还有四个额外的提示:
- 请记住,(几乎)每个算术和逻辑运算之后都会设置标志。因此,在
之后确实不需要执行add
,特别是当跳转的唯一条件可以由一个标志表示时。在这种情况下,cmp
可以被一个非常简单的add ecx,1/cmp al,0/je hang
替换。这将为您节省两个字节,在这些引导扇区条件下非常有价值add ecx,1/jz hang
- 调用BIOS例程时,您确实希望保留应用程序中使用的寄存器。BioSe来自不同的供应商,其中一些供应商可能不会很好地发挥作用,并破坏您的注册表中的内容。指令
就是这样做的。通常,在调用您自己没有编写的任何代码时,保存所有运行时信息是一条经验法则(尽管在更“文明”的环境中这听起来可能有些极端,但BIOS和通用实模式代码不是其中之一)pusha
- 当计算机启动时,它处于实模式。此模式下的默认操作数和地址大小为16位(通过分段将地址人为扩展为20位)。当然,您可以使用寄存器的32位部分,但必须在指令之前生成操作数大小前缀才能使用。这是另一个字节,您现在只有510个。:)因此,
只是冗余的-地址的偏移部分永远不会超过16位。这同样适用于mov ecx,msg
。在这两种情况下,只需将添加ecx,1
替换为ecx
cx
- 使用
说明。它使你的CPU的血压低得多,而且到处给它施加压力是没有用的。只需在hlt
标签之后和跳转之前添加hang
hlt
- 您的程序正以您编写的方式工作。ASCII中的小写字母
e
表示为65h
,在十进制中等于101。因此,如果e
(101)处于al
中,则执行cmp al,100/jge hang
将导致跳转到标签hang
。一切都很好
您的问题的一个解决方案是简单地删除该行,因为我看不出它有什么用途-看看您是如何让字符串以\0
结尾的,循环将在到达末尾时结束
不过,还有四个额外的提示:
- 请记住,(几乎)每个算术和逻辑运算之后都会设置标志。因此,在
之后确实不需要执行add
,特别是当跳转的唯一条件可以由一个标志表示时。在这种情况下,cmp
可以被一个非常简单的add ecx,1/cmp al,0/je hang
替换。这将为您节省两个字节,在这些引导扇区条件下非常有价值add ecx,1/jz hang
- 调用BIOS例程时,您确实希望保留应用程序中使用的寄存器。BioSe来自不同的供应商,其中一些供应商可能不会很好地发挥作用,并破坏您的注册表中的内容。指令
就是这样做的。通常,在调用您自己没有编写的任何代码时,保存所有运行时信息是一条经验法则(尽管在更“文明”的环境中这听起来可能有些极端,但BIOS和通用实模式代码不是其中之一)pusha
- 当计算机启动时,它处于实模式。此模式下的默认操作数和地址大小为16位(通过分段将地址人为扩展为20位)。当然,您可以使用寄存器的32位部分,但必须在指令之前生成操作数大小前缀才能使用。这是另一个字节,您现在只有510个。:)因此,
只是冗余的-地址的偏移部分永远不会超过16位。这同样适用于mov ecx,msg
。在这两种情况下,只需将添加ecx,1
替换为ecx
cx
- 使用
说明。它使你的CPU的血压低得多,而且到处给它施加压力是没有用的。只需在hlt
标签之后和跳转之前添加hang
hlt
[BITS 64]
生成64位汇编代码,它处于16位模式?为什么在计算机启动时使用[BITS 64]
生成64位汇编代码,它处于16位模式?谢谢您这样做修复了我的问题。我现在觉得自己真的很笨。谢谢你这么做解决了我的问题。我现在觉得自己很愚蠢。