我按照书中的说明操作。我正在尝试在QEMU上的i8086上编写一个简单的引导程序。 我正在使用BIOS中断(INT 10,E - 在电传打字模式下写文本)打印出我手头设置的位置上的字符,同时还有BIOS中断(INT 10,2 - 设置光标位置)。
设置光标位置有效。
我的目标是创建一个子程序“PutChar”,它将char作为参数然后打印出来。直接打印char(即mov al, 'c'
)工作正常,这表明它实际上可以工作。
寄存器AL
将要打印的字符。
寄存器AH
定义了应该用INT 10h执行哪个函数。
我把一个明星放在实际参数应该复制到AH的地方。
但是,在某个地方,我犯了一个我找不到的错误。我一次又一次地计算如果我在堆栈上正确引用'A',我甚至只是出于绝望而尝试[bp],[bp + 8]和[bp + 16]。
运行这些结果没有任何打印,甚至没有“怪异”的ASCII字符,这让我相信参考地址上没有任何内容。显然我在某处错了,但在哪里?
以下代码:
;********************
;A simple bootloader
;*******************
org 0x7c00
bits 16
start:
call MoveCursor
push 'A' ; SP--, then put 'A' on stack. (8 bit only)
call PutChar
jmp boot
MoveCursor:
mov bh, 0
mov dh, 11
mov dl, 10
mov ah, 02h
int 10h
ret
PutChar:
push bp ; SP--, SP--, then put Base Pointer on stack (16 bit)
mov bp, sp ;Copy Stack Pointer to Base Pointer
*mov al, [bp+16] ;Since [bp] points to the old Base Pointer and the Base Pointer is 16 bits long, going back 16 bit would result in 'A', right?
mov ah, 0eh
int 10h
pop bp
ret
boot:
cli ;no interrupt
cld ;all that we need to init
hlt ;halt the system
;We have to be 512 bytes. Clear the rest of the bytes with 0
times 510 - ($-$$) db 0
dw 0xAA55
感谢@Margaret Bloom我解决了它。我实际上做了错误的计算,而且我也没有考虑到[bp+8]
实际上意味着在bp
之后的8个字节而不是像我最初假设的那样。现在思考,字节只是逻辑 - 我的错误。
然后,我忘了调用一个函数也会添加到堆栈中:当然是返回地址。
因此,在下面的顺序值被推入堆栈:
然后我将SP保存到BP并使用BP来引用我的参数'A'。由于[BP]是我的SP,[BP + 2]将是我的返回地址,最后[BP + 4]是我的参数。
注意,正如我所说,+ 2表示2个字节,而不是位。