我正在尝试在nasm中编写一个bootloader,此时它只是打印一个字符串。
[BITS 16]
[org 0x7c00]
myString:
db 'Hello World', 0x00
mov bp, 0x8000
mov sp, bp
mov bx, myString
call printString
jmp $
printString:
pusha
mov ah , 0x0e
printStringA:
mov al , [bx]
cmp al, 0x00
je printStringB
int 0x10
add bx, 0x01
jmp printStringA
printStringB:
popa
ret
times 510 -( $ - $$ ) db 0
dw 0xaa55
工作正常,但如果我将字符串定义移动到此处:
[BITS 16]
[org 0x7c00]
mov bp, 0x8000
mov sp, bp
myString:
db 'Hello World', 0x00
mov bx, myString
call printString
jmp $
printString:
pusha
mov ah , 0x0e
printStringA:
mov al , [bx]
cmp al, 0x00
je printStringB
int 0x10
add bx, 0x01
jmp printStringA
printStringB:
popa
ret
times 510 -( $ - $$ ) db 0
dw 0xaa55
它打印出垃圾,我在windows下的bochs中运行它,如果这有帮助的话。
答案 0 :(得分:1)
您正在组装到原始机器代码。没有数据和文本部分。一切都被解释为代码,包括使用db插入的内容。因此两个代码段都是错误的。
如果您使用无限循环(如示例中所示)或暂停指令,则可以安全地将数据放在代码之后,因为它永远不会到达。否则,您必须安排跳过数据。
您还需要在开始时正确设置段寄存器。
这是一个更正版本,早期声明数据:
[BITS 16]
[org 0x7c00]
;;; Set CS and DS
jmp 0:start
start:
mov ax, cs
mov ds, ax
;;; set SP
mov bp, 0x8000
mov sp, bp
;;; skip over data
jmp L1
myString:
db 'Hello World', 0x00
L1:
mov bx, myString
...
请注意,在第一个示例中,数据被解释为代码。
db 'Hello World', 0x00
组装为
48 65 6c 6c 6f 20 57 6f 72 6c 64 00
并对应于:
dec ax
gs insb
insb
outsw
and [bx+0x6f],dl
jc short 0x76
fs
db 0x00
实际上,这会在您的代码之前执行。幸运的是,这个片段并没有阻止你的代码工作。