首页 > 解决方案 > 我正在尝试使用汇编中的星号制成的圣诞树创建引导加载程序,但我不知道如何使用相同的循环进行打印

问题描述

我试图得到这样的东西

    *
   ***
  *****
 *******
*********
   ***
   ***

我已经学会了如何创建一个循环并尝试调整相同的代码以多次使用该循环但失败了。以下是我到目前为止编写的代码

[BITS 16] 
[ORG 0x7C00] 
top: 
    ;; Put 0 into ds (data segment) 
    ;; Can't do it directly 
    mov ax,0x0000 
    mov ds,ax 
    ;; si is the location relative to the data segment of the 
    ;; string/char to display 
    mov si, fourSpace
    call writeString
    mov ch, 1 ; mov 1 into the register ch
    call dotsLoop
    mov si, threeSpace
    call writeString
    mov ch, 3 ; mov 3 into the register ch
    call dotsLoop
    mov si, twoSpace
    call writeString
    mov ch, 5 ; mov 5 into the register ch
    call dotsLoop
    mov si, oneSpace
    call writeString
    mov ch, 7 ; mov 7 into the register ch
    call dotsLoop
    mov ch, 9 ; mov 9 into the register ch
    call dotsLoop
    mov si, branchThreeSpace1
    call writeString
    mov ch, 3 ; mov 3 into the register ch
    call dotsLoop
    mov si, branchThreeSpace2
    call writeString
    mov ch, 3 ; mov 3 into the register ch
    call dotsLoop
 
    jmp $ ; Spin 
    
dotsLoop:
    mov si, dot ; print the dot
    call writeString ; See below 
    dec ch ; reduce what is in ch by 1
    cmp ch, 0 ; compare to see if what is store in ch is 0
    jne dotsLoop ; if ch does not contain 0 call dotsLoop again.
    mov si, cr ; print the newline code
    call writeString ; See below 
    ret ; when ch contains 0 return back to main code 
    
    
writeString: 
    mov ah,0x0E ; Display a chacter (as before) 
    mov bh,0x00 
    mov bl,0x07 
nextchar: 
    Lodsb ; Loads [SI] into AL and increases SI by one 
    ;; Effectively "pumps" the string through AL 
    cmp al,0 ; End of the string? 
    jz done 
    int 0x10 ; BIOS interrupt 
    jmp nextchar 
done: 
    ret 
    fourSpace db '    ',0 ; For spacing
    1dot db '*', 13,10,0
    threeSpace db '    ',0 ; For spacing
    3dot db '*',13,10,0
    twoSpace db '    ',0 ; For spacing
    5dot db '*',13,10,0
    oneSpace db '    ',0 ; For spacing
    7dot db '*',13,10,0
    9dot db '*',13,10,0
    branchThreeSpace1 db '    ',0 ; For spacing
    branchdot1 db '*',13,10,0
    branchThreeSpace2 db '    ',0 ; For spacing
    branchdot2 db '*',13,10,0
    times 510-($-$$) db 0
    dw 0xAA55

但是,正如预期的那样,我在这些行的行错误开始时得到了预期的标签或指令

1dot db '*', 13,10,0
3dot db '*',13,10,0
etc..

谁能指导我如何将 dotsLoop 用于多个实例?

标签: assemblynasmx86-16bootloader

解决方案


1dot       db '*',13,10,0
3dot       db '*',13,10,0
5dot       db '*',13,10,0
7dot       db '*',13,10,0
9dot       db '*',13,10,0
branchdot1 db '*',13,10,0
branchdot2 db '*',13,10,0

就像 Michael Petch 在评论中所写的那样,NASM 标签不能以数字 0-9 开头。
接下来,因为所有这些行都有相同的内容,所以你不需要重复 7 次。CH登记册将使您所需要的一切变得不同。
此外,为了在程序中正确操作,您需要从行中删除该回车符和换行符对。
这是剩下的:

dot db '*', 0

fourSpace         db '    ',0 ; For spacing
threeSpace        db '    ',0 ; For spacing
twoSpace          db '    ',0 ; For spacing
oneSpace          db '    ',0 ; For spacing
branchThreeSpace1 db '    ',0 ; For spacing
branchThreeSpace2 db '    ',0 ; For spacing

在这里,你也在重复自己 6 次!同样重要的是,您没有输出所需数量的空格!每次你写 4 个空格,因此不会产生圣诞树。

您可能需要的只是:

fourSpace  db ' '
threeSpace db ' '
twoSpace   db ' '
oneSpace   db ' ', 0

threeSpacebranchThreeSpace1branchThreeSpace2之间确实没有区别。它们都应该精确地输出 3 个空格字符。


谁能指导我如何将 dotsLoop 用于多个实例?

将上述内容应用于您的代码,您会发现它会起作用:

...
mov  si, fourSpace
call writeString
mov  ch, 1
call dotsLoop
mov  si, threeSpace
call writeString
mov  ch, 3
call dotsLoop
mov  si, twoSpace
call writeString
mov  ch, 5
call dotsLoop
mov  si, oneSpace
call writeString
mov  ch, 7
call dotsLoop
mov  ch, 9
call dotsLoop
mov  si, threeSpace
call writeString
mov  ch, 3
call dotsLoop
mov  si, threeSpace
call writeString
mov  ch, 3
call dotsLoop
jmp  $ 
dotsLoop:
...
writeString: 
...
dot        db '*', 0
fourSpace  db ' '
threeSpace db ' '
twoSpace   db ' '
oneSpace   db ' ', 0
cr         db 13, 10, 0
...

推荐阅读