Loops 为什么此ASM功能不能正确打印?

Loops 为什么此ASM功能不能正确打印?,loops,assembly,io,x86,mbr,Loops,Assembly,Io,X86,Mbr,我正在尝试编写一个小函数来打印特定内存位置中以null结尾或固定长度的字符串。这是我的密码: vbrstart: xor eax, eax mov sp, 0x7a00 mov bp, 0x6000 mov ss, ax mov ds, ax mov es, ax xor ebx, ebx xor ecx, ecx push strict dword initializing push strict word 0x0

我正在尝试编写一个小函数来打印特定内存位置中以null结尾或固定长度的字符串。这是我的密码:

vbrstart:
    xor eax, eax
    mov sp, 0x7a00
    mov bp, 0x6000
    mov ss, ax
    mov ds, ax
    mov es, ax
    xor ebx, ebx
    xor ecx, ecx
    push strict dword initializing
    push strict word 0x0000
    call printmsg
    jmp end


;push strict dword memloc
;push strict word length
;call printmsg
printmsg:
    pop strict dword [store_ret]
    mov [store_cx], cx
    mov [store_esi], esi
    pop cx
    pop esi
    push eax
    push ebx
    mov ah, 0x0E
    mov bx, 0x0007
    cmp cx, 0x0000
    je printnullterm
printgivenlen:
    lodsb
    cmp cx, 0x0000
    je printdone
    int 10h
    dec cx
    jmp printgivenlen
printnullterm:
    lodsb
    cmp al, 0x00
    je printdone
    int 10h
    jmp printnullterm
printdone:
    pop ebx
    pop eax
    mov esi, [store_esi]
    mov cx, [store_cx]
    push strict dword [store_ret]
    ret
printdata:
    store_cx dw 0
    store_esi dd 0
    store_ret dd 0

end:
    hlt
    jmp end

initializing db 10,13,'Initializing...',0

测试时,它会不确定地打印,并且不会在空字节处停止。我在哪里出错了?

您的堆栈没有与所有推送和弹出的对象正确对齐。检查传递的参数及其在例程中的使用情况。 首先,这里有一个提示:

vbrstart:
xor eax, eax
mov sp, 0x7a00
mov bp, 0x6000
mov ss, ax
mov ds, ax
mov es, ax
xor ebx, ebx
xor ecx, ecx
push strict dword initializing
push strict word 0x0000
call printmsg                   ; near call, only 16 bits ret addr stored
jmp end

;push strict dword memloc
;push strict word length
;call printmsg
printmsg:
    pop strict dword [store_ret]    ; pop dword (ret address + 16 bits- 1st argument)
    mov [store_cx], cx              ; store_cx = 0
    mov [store_esi], esi            ; store_esi = ??
    pop cx                          ; cx = initializing
    . . .

我发现您的代码有两个问题:

  • 您已经编写了一个引导加载程序。这样的程序在16位实地址模式下运行。这意味着
    呼叫
    的返回地址将是一个单词,而不是代码所期望的dword

    printmsg:
    pop word [store_ret]
    
  • 您以一种危险的方式设置堆栈。您需要首先更改SS寄存器,然后立即更改SP寄存器

    xor ax, ax
    mov ss, ax      <<< Keep these together 
    mov sp, 0x7a00  <<< and in this order!
    

    使用调试器看看哪里出了问题,怎么样?调试器没有详细说明哪个寄存器中有什么,以及调试的哪个部分被卡住。将其编译为调试器可以使用的ELF二进制文件,并将其编译为平面二进制文件,我使用它,添加到VBR,提供了不同的代码和结果,所以调试器并没有给我提供太多有用的信息。如果有人知道支持平面二进制文件的免费调试器,请告诉我。。。那会有很大帮助。。。我可以卸载或反汇编,但这是关于所有bochs内置调试器或将gdb附加到bochs或qemu的。PS:现在还不清楚你处于什么模式,小心混合16位和32位的东西,尤其是你的堆栈操作看起来很奇怪。所以我不需要存储ret地址?我首先想到的是我的论点?
    push word initializing
    ...
    pop si