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

Assembly 8086不打印第一个字符,而是打印空字符,assembly,nasm,x86-16,bootloader,bios,Assembly,Nasm,X86 16,Bootloader,Bios,此代码中有一个错误。print_字符串在指向字符串后不会打印到屏幕上,它只在代码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

此代码中有一个错误。print_字符串在指向字符串后不会打印到屏幕上,它只在代码
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
让你的印刷步入正轨 设置堆栈的方式有很多错误。做两次也帮不了什么忙!此外,在设置堆栈指针时,始终首先分配
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

这个打印例程仍然需要您说出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
一旦您确信这部分代码工作正常,您只需删除这两行代码


最终会适得其反的事情 请使用显式零结束字符串。不要依赖以下恰好使用零的填充

今后:

  • 您可以使用非零的其他值填充
  • 引导加载程序可能很拥挤,因此根本没有填充
我的回答补充了解决印刷(及更多)问题的方法。
它处理的是在输入了大量字符后程序不断崩溃的事实

问题在于这一行:

和它的同伴:

由于堆栈段现在正确定位为0,因此不应再存储从
bp=0开始的字符。您可以在alloc code
mov[bp],al
中执行此操作

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

SEAM_STD_BUFFER equ 0x7E00

你是16位汇编代码开发新手吗?我问你,因为你的函数操作方式、不寻常的dalloc例程以及你在代码顶部错误地设置了段寄存器。是的,我是新手,请告诉我如何设置段寄存器。我将从一开始就非常简单。暂时忘记输入。你有没有尝试过创建只在屏幕上显示字符串的工作代码?是的,它可以很好地打印所有内容,除了我添加mov bp,8000h mov ss,bp它会出错。你已经标记了这个emu8086。它看起来像nasm。您使用的是emu8086吗?谢谢您的回答:),输入这么多字符后代码仍然会冻结,我确实更改了初始化,在字符串中添加了终止符,并在打印标签中指定了页码。谢谢,但是为什么不在[0:0]中移动内容呢x86上的work?@Dodo中断向量表占用内存中从0000h:0000h->0000h:0400h的1024个最低地址。如果你在这个区域写随机的东西,那么中断向量就会被破坏,很快计算机就会挂起!
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
SEAM_STD_BUFFER equ 0x7E00