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

您没有正确设置 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

一定要以明确的零结束字符串。不要依赖以下恰好使用零的填充。

未来:

  • 您可能会用零以外的其他值填充
  • 引导加载程序可能会变得拥挤,所以根本没有填充

我的回答补充了 解决了打印(以及更多)问题。
处理输入多个字符后程序一直崩溃的问题

问题出在这一行:

SEAM_STD_BUFFER equ 0

及其同伴:

mov bp,SEAM_STD_BUFFER

因为堆栈段现在正确定位在 0,所以您不应再存储从 bp=0 开始的字符。您在 alloc 代码 mov [bp], al.

中执行此操作

您可以将它存储在许多其他地方,但最好的一个将直接放在引导加载程序后面。

SEAM_STD_BUFFER equ 0x7E00