我正在尝试创建一个引导加载程序,并在汇编中用星号制成的圣诞树,但我无法弄清楚如何使用相同的循环进行打印



我正在尝试获得类似的东西

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

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

[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用于多个实例吗?

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

threeSpacebranchThreeSpace1BranchThreeSpace 2之间真的没有区别。它们都应该精确输出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
...

最新更新