此代码有错误。指向字符串后,print_string不会打印到屏幕上,它仅在代码mov bx,8000h
中的行被删除并且其后的两行才打印,但是然后我不能写很多字节来使整个崩溃在调用alloc并将基指针增加20次之后。我该怎么办,如何写该字符串,并使其在写入20个字节后不会崩溃
[bits 16]
[org 0x7c00]
SEAM_STD_BUFFER equ 0
SEAM_STD_LIMIT equ 255
xor ax,ax
mov bx,ax
mov bx,cx
mov dx,0
mov ds,bx
mov es,bx
mov bp,0
mov sp,bp
mov ss,bp
mov bx,8000h
mov sp,bx
mov ss,bx
mov bp,0
jmp _start
_start:
call clear
.repeat:
mov bp, OS_USERNAME_DESCRIPT
call print_string
call Set_BasePointer_std
call read_string_show
jmp .repeat
Set_BasePointer_std:
mov bp,SEAM_STD_BUFFER
ret
read_char_show:;() returns al
call read_char
cmp al,8
je .back
call print
ret
.back:
cmp bp,SEAM_STD_BUFFER
je .done
call print
.done:
mov al,0
ret
read_string: ; (ptr bp place to allocate string)
call read_char
cmp al,13
je .done
call alloc
inc bp
cmp bp,SEAM_STD_LIMIT
jge .resetbp
jmp read_string
.done:
mov al,0
call alloc
ret
.resetbp:
call Set_BasePointer_std
jmp read_string
read_string_show: ; (ptr bp place to allocate string)
call read_char_show
cmp al,0
je read_string_show
cmp al,13
je .done
cmp al,8;;NOT GOOD ENOUGH
je .skip;;NOT GOOD ENOUGH
call alloc
inc bp
.skip:;;NOT GOOD ENOUGH
cmp bp,SEAM_STD_LIMIT
jge .resetbp
jmp read_string_show
.resetbp:
call Set_BasePointer_std
jmp read_string
.done:
mov al,0
call alloc
call next_line
ret
read_char: ;() returns al
mov ax,0x00
int 0x16
ret
clear:; ()
mov ah,0
mov al,3
int 0x10
ret
free:;(bp ptr at place start to free, ax at end )
mov [bp],byte 0
cmp bp,ax
je .done
inc bp
jmp free
.done:
ret
dalloc:; (ptr bp)
mov al,[bp]
ret
alloc: ;(bp place to allocate,al byte value)
mov [bp], al
ret
clear_line:
mov dh,0
call clear
ret
next_line:
mov ah,2
mov dl,0
inc dh
cmp dh ,25
jge clear_line
int 10h
ret
previous_line:
dec dh
mov ah,2
mov dl,0
int 10h
ret
next_char:; finish
string_compare:;finish
print: ; (al Character to print, bl color)
mov ah,0x0E
int 10h
ret
print_string: ;(ptr bp Place of string start)
call dalloc
cmp al,0
je .done
call print
inc bp
jmp print_string
.done:
ret
OS_WELCOME db 'What is giong on',0
OS_USERNAME_DESCRIPT db 'Username:'
times (510 - ($-$$)) db 0x00
dw 0xAA55
答案 0 :(得分:2)
xor ax,ax mov bx,ax mov bx,cx <-- Here CX goes to BX mov dx,0 mov ds,bx <-- Here (via BX) CX goes to DS mov es,bx <-- Here (via BX) CX goes to ES
您没有正确设置DS
和ES
段寄存器!
您已经将CX
的值存储在其中,但是CX
从未使用任何有用的值进行初始化。
mov bp,0 mov sp,bp mov ss,bp mov bx,8000h mov sp,bx mov ss,bx
设置堆栈的方式有很多错误。这样做两次无济于事!同样,在设置堆栈指针时,始终首先分配SS
,然后立即分配SP
。顺序很重要。
坦率地说,要输入SS
的实际值,您别无选择。 (从技术上讲,您有,但让我们不复杂...)假设您想使用BP
指向字符串,并且整个程序都使用ORG 0x7C00
进行编码,这是唯一可放入的正确值SS
为零。
我建议你写:
xor ax, ax
mov ss, ax
mov sp, 0x7C00
这会将堆栈放在安全的引导加载程序下面。
而且由于DS
和ES
也需要良好的初始化,因此请完成整个操作:
xor ax, ax
mov ss, ax
mov sp, 0x7C00
mov ds, ax
mov es, ax
print: ; (al Character to print, bl color) mov ah,0x0E int 10h ret
此 print 例程仍然需要您说BIOS电传打字功能应写在哪个显示页面上。通过BH
寄存器进行选择。
print:
mov bh, 0
mov ah, 0x0E
int 10h
ret
为了验证打印效果,您可以让程序等待按键:
_start:
call clear
.repeat:
mov bp, OS_USERNAME_DESCRIPT
call print_string
mov ah, 00h ;Wait for a key
int 16h ;Wait for a key
一旦您确信代码的这一部分工作正常,只需删除这两行即可。
OS_USERNAME_DESCRIPT db 'Username:' times (510 - ($-$$)) db 0x00
请使用显式零终止字符串。不要依赖于恰好使用零的以下填充。
将来:
答案 1 :(得分:0)
我的回答是the answer given by Sep Roland的补充,它解决了打印问题(以及更多)。
它处理了一个事实,即在输入许多字符后,程序始终崩溃。
问题出在这一行:
SEAM_STD_BUFFER equ 0
及其同伴:
mov bp,SEAM_STD_BUFFER
由于堆栈段现在正确定位在0上,因此您不应再存储从bp=0
开始的字符。您可以在 alloc 代码mov [bp], al
中进行此操作。
您可以将其存储在许多其他地方,但是好的一个将直接放在引导加载程序的后面。
SEAM_STD_BUFFER equ 0x7E00