Assembly 中断10h的功能06h。滚动文本行
我需要使用中断10h的功能06h实现滚动排队。问题是我有滚动的行,但符号没有显示,光标消失,什么也没有发生。也许我忘了要考虑的事情了?要编写代码,我使用Assembly 中断10h的功能06h。滚动文本行,assembly,x86,bootloader,fasm,video-memory,Assembly,X86,Bootloader,Fasm,Video Memory,我需要使用中断10h的功能06h实现滚动排队。问题是我有滚动的行,但符号没有显示,光标消失,什么也没有发生。也许我忘了要考虑的事情了?要编写代码,我使用FASM。该代码是引导加载程序的一部分。下面是一段与滚动相关的代码: cmp cx, 2001 je ScrollLine 我有一个计数器,当它达到2001(从1开始计数)时,控制传递到ScrollLine 滚动线: mov ah, 06h mov al, 1 mov bh, 07 mov cx, 0000h mov dx, 184
FASM
。该代码是引导加载程序的一部分。下面是一段与滚动相关的代码:
cmp cx, 2001
je ScrollLine
我有一个计数器,当它达到2001(从1开始计数)时,控制传递到ScrollLine
滚动线:
mov ah, 06h
mov al, 1
mov bh, 07
mov cx, 0000h
mov dx, 184Fh
int 10h
ret
我的完整引导加载程序代码如下:
use16
org 7C00h
start:
mov ah, 00h
mov al, 02h
int 10h
mov ax, NewInt40
call ChangeIVT
mov cx, 0
wait_loop:
xor ax, ax
inc cx
cmp cx, 2001
je ScrollLine
mov ah, 0
int 16h
push ax
call PrintChar
jmp wait_loop
NewInt40:
sti
push ax
mov ax, msg
cmp bl, 3
je PrintChar
cmp bl, 2
je PrintString
cmp bl, 1
je Clear
cmp bl, 4
je Scroll
pop ax
iret
ChangeIVT:
push bx
xor bx, bx
mov es, bx
mov bx, 40h
shl bx, 2
mov word [es:bx], ax
mov word [es:bx+2], 0
pop bx
ret
PrintString:
push si
push bx
push es
mov si, ax
mov ax, 0B800h
mov es, ax
xor bx, bx
xor dx, dx
@@:
lodsb
cmp al, 0
je @f
mov byte [es:bx], al
mov byte [es:bx+1], 1Eh
mov ah, 0Eh
add bx, 2
inc dx
mov ah,02h
mov al,02h
int 10h
jmp @b
@@:
pop es
pop bx
pop si
ret
PrintChar:
push bp
mov bp, sp
push bx
push es
push cx
mov ax, 0B800h
mov es, ax
xor bx, bx
xor dx, dx
mov ah,3
int 0x10
movzx ax, dh
movzx bx, dl
mov cx, 80
push dx
mul cx
pop dx
add bx, ax ; bx = 80 * dh + dl
shl bx, 1 ; bx = 2 * (80 * dh + dl)
mov ax, [bp + 4]
mov byte [es:bx], al
mov byte [es:bx+1], 1Eh
cmp dl, 79
jl @f
inc dh
mov dl, -1
@@:
inc dl
pop cx
mov bh, 0
mov ah, 2
int 0x10
pop es
pop bx
mov sp, bp
pop bp
ret
Clear:
mov AH,0
mov AL,2
int 10H
ret
Scroll:
mov ah, 06h
mov al, 1
mov bh, 07
mov cx, 0000h
mov dx, 184Fh
int 10h
ret
ScrollLine:
mov bl, 4
int 40h
xor cx, cx
ret
msg db "Hello, world!", 0Dh, 0Ah, 0
db 510-($-$$) dup (0)
db 55h, 0AAh
你在用跳跃呼叫
在NewInt40
ISR中,您可以有条件地跳转到子例程PrintString
,PrintChar
,滚动
,等等,但从这些子例程返回ret
我不知道代码是如何构造的,所以我只介绍了使其工作所需的最小的更改,没有什么可以称为良好实践
由于您正在编写引导加载程序,您现在肯定知道要修复什么了
NewInt40:
sti
push ax
push bp ;; Save caller's BP
mov bp, sp ;; Save SP, so we can restore the stack pointer
push WORD _ni40_end ;; Push return address of every routine
mov ax, msg
cmp bl, 3
je PrintChar
cmp bl, 2
je PrintString
cmp bl, 1
je Clear
cmp bl, 4
je Scroll
_ni40_end: ;; NASM label
mov sp, bp ;; Restore stack pointer (in any case)
pop bp ;; Restore caller BP
pop ax
iret
对不起,我是为NASM写的,不过翻译成FASM应该很容易
附加说明当您的引导加载程序“变得疯狂”时,如不响应或自行行动,很可能是您“失去了执行流程”的症状。
这意味着您正在执行的字节不是您的代码,当您返回的堆栈不平衡时,就会发生这种情况。
如果类似情况再次发生,请仔细检查您的报税表。因此,您在报税表上显示了一个字符,例如,在报税表上显示了一个字符,而这正是问题出现的时间?文本滚动,但随后输出出现问题?您可以发布更多代码吗?简单的演示程序(用于NASM)使用与您相同的中断调用,运行良好。@MargaretBloom:有点吹毛求疵,但在您的代码中,当您创建COM程序时设置SS:SP、DS等有什么意义(我假设从org 100h开始)?DOS加载器自动加载COM程序,并将其全部设置为同一段,并在64k段的顶部适当设置堆栈。CS=DS=SS全部指向PSP段的开始。@MichaelPetch。啊。。引导加载程序的坏习惯(编码:)@汤米:是的。我有一个处理键盘输入的循环<代码>等待循环:xor ax,ax inc cx cmp cx,2001 je滚动线mov ah,0 int 16h jmp等待循环他在执行时也会犯类似错误。Scrollline还做了一个
ret
代码中的另一个特殊问题是push ax
调用PrintChar
。我从未见过他在调用完成后清理堆栈和删除参数。@MichaelPetch我完全理解,但我需要一个条件跳转,返回到程序。毕竟,如果我要使用调用
,我就不能进入条件。我为我的英语感到抱歉。谢谢你的评论和建议corrections@MargaretBloom@MichaelPetch我知道我犯了一个错误。但我不知道如何在条件允许的情况下拨打电话。我只知道一种方法-cmp
和j(e、ne、a等)。是的,不使用call
的ret
是不可接受的。我明白了。我只是有点困惑,对吗now@P.Fiona玛格丽特提出了一个可能的解决办法。手动将返回地址推送到堆栈上,执行条件跳转,然后ret
将返回推送到堆栈上的地址。或者(对于您的思维方式来说可能更简单)是有条件地跳转到一个标签,然后调用预期的函数。