8086不打印第一个字符,而是打印空值

时间:2018-07-22 08:00:28

标签: assembly nasm x86-16 bootloader bios

此代码有错误。指向字符串后,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

2 个答案:

答案 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

您没有正确设置DSES段寄存器!
您已经将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

这会将堆栈放在安全的引导加载程序下面。
而且由于DSES也需要良好的初始化,因此请完成整个操作:

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