8086 不打印第一个字符而是打印空值
8086 not printing first character printing nulls instead
这段代码有错误。 print_string 在指向字符串后不会打印到屏幕上,它只会在代码 mov bx,8000h
中的行被删除以及它后面的两行时打印,但是我不能向 ram 写入很多字节在调用 alloc 并将 basepointer 递增 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
让您的打印步入正轨
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
一定要以明确的零结束字符串。不要依赖以下恰好使用零的填充。
未来:
- 您可能会用零以外的其他值填充
- 引导加载程序可能会变得拥挤,所以根本没有填充
我的回答补充了 解决了打印(以及更多)问题。
处理输入多个字符后程序一直崩溃的问题
问题出在这一行:
SEAM_STD_BUFFER equ 0
及其同伴:
mov bp,SEAM_STD_BUFFER
因为堆栈段现在正确定位在 0,所以您不应再存储从 bp=0
开始的字符。您在 alloc 代码 mov [bp], al
.
中执行此操作
您可以将它存储在许多其他地方,但最好的一个将直接放在引导加载程序后面。
SEAM_STD_BUFFER equ 0x7E00
这段代码有错误。 print_string 在指向字符串后不会打印到屏幕上,它只会在代码 mov bx,8000h
中的行被删除以及它后面的两行时打印,但是我不能向 ram 写入很多字节在调用 alloc 并将 basepointer 递增 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
让您的打印步入正轨
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
一定要以明确的零结束字符串。不要依赖以下恰好使用零的填充。
未来:
- 您可能会用零以外的其他值填充
- 引导加载程序可能会变得拥挤,所以根本没有填充
我的回答补充了
处理输入多个字符后程序一直崩溃的问题
问题出在这一行:
SEAM_STD_BUFFER equ 0
及其同伴:
mov bp,SEAM_STD_BUFFER
因为堆栈段现在正确定位在 0,所以您不应再存储从 bp=0
开始的字符。您在 alloc 代码 mov [bp], al
.
您可以将它存储在许多其他地方,但最好的一个将直接放在引导加载程序后面。
SEAM_STD_BUFFER equ 0x7E00