【发布时间】:2019-04-23 12:33:39
【问题描述】:
所以我目前正在处理一个简单的程序集块,我希望将其变成一个高效的引导加载程序来加载 C 内核。
我现在的主要问题是。是否有任何关于我当前如何从 SI 寄存器中存储和打印字符串的指针?
它完美地呈现了字符串。我只是想确保我正在开发良好的做法。
这是我的代码。
ORG 0x7c00
msg db 'Hello World!', 0
start:
mov ax, 0x00
mov ds, ax
mov ah, 0x0e ;prepare AH register to be written to.
mov si, msg ;move string into SI register and prepare for read/write
call print
print:
lodsb ;load byte string pointed to in SI and DS register
or al, al ;check if al equals 0
jz end ; if zero, end execution
int 0x10 ;print string
jmp print ;^ above line and this only execute if AL > 0.
end:
hlt
jmp end
times 510-($-$$) db 0
dw 0xaa55
【问题讨论】:
-
没有人关心在使用 bios 服务启动期间打印字符串的效率。绝对不好的做法是在不是函数的东西上使用
call。此外,您不应将数据放在0x7c00,因为这是引导扇区的入口点(无论您可能在哪里放置start标签),因此cpu 将尝试执行任何代码.意思是,将msg移动到jmp end之后,使其不在执行路径中。 -
在引导加载程序中,唯一重要的“效率”衡量标准是代码大小。由于限制为 510 字节,您需要以尽可能少的代码字节完成工作。也就是说,您的代码在代码大小和效率方面都很糟糕。
xor ax,ax比mov ax,0短,根本不需要使用call。只是陷入循环。or al,al的大小相同,但比test al,al差,而且您知道第一个字节不是终止符,因此您可以对其进行重构:Why are loops always compiled into "do...while" style? -
另请参阅Tips for golfing in x86/x64 machine code 了解更多信息。您可以考虑在循环底部使用缓慢但很小的
loop指令。当然,为了提高效率,如果 BIOS 具有一次调用打印多个字符的任何功能,那将快得多。int是一条很慢的指令,因此只为整个字符串创建一条指令要快得多。