我正在按照一本书中的说明进行操作。我正在尝试在QEMU的i8086上编写一个简单的引导程序。
我正在使用BIOS中断(INT 10,E-在电传模式下写入文本)在我预先设置的位置上打印出一个字符,同时也在BIOS中断(INT 10,2-设置光标位置)上打印了一个字符。
设置光标位置有效。
我的目标是创建一个子程序“ PutChar”,该子程序将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
答案 0 :(得分:2)
感谢@Margaret Bloom,我解决了它。
我实际上没有计算错了,我也没有考虑到[bp+8]
实际上是指bp
之后的8个字节而不是位就像我最初假设的那样。现在想想,字节只是逻辑上的-我的错误。
然后,我忘记了调用函数还会添加到堆栈中:当然是返回地址。
因此,按以下顺序将值压入堆栈:
然后将SP保存到BP中,并使用BP引用我的参数'A'。 因为[BP]是我的SP,所以[BP + 2]是我的寄信人地址,最后[BP + 4]是我的参数。
请注意,正如我所说,+ 2表示2个字节而不是位。