[英]Assembly - (NASM 32-bit) Printing a triangle of stars not working properly
[英]How to print a triangle of stars in assembly?
我需要獲得以下輸出:
*
**
***
****
*****
******
*******
********
*********
**********
所以它的10行,我的星星將從1開始,然后到10。
目前我得到:
**********
***********
************
*************
**************
***************
****************
*****************
******************
*******************
********************
我的代碼:
section .data
char db ' '
trianglesize db 0; ;stars per line
trianglerows db 10;
section .text
global _start
_start
mov rax, [trianglerows] ;rows
outer_loop:
mov rbx, [trianglerows]
inner_loop:
call star
dec bx
cmp bx,0
jg inner_loop
call newline
call down_triangle
dec ax
cmp ax, 0
jne outer_loop
call newline
call exit
exit:
mov eax,1 ;sys_exit
mov ebx,0 ;return 0
int 80h;
ret
newline:
mov [char],byte 10
push rax;
push rbx;
mov eax,4; ;sys_write
mov ebx,1; ;stdout
mov ecx, char;
mov edx,1; ;size of new line
int 80h
pop rbx;
pop rax;
ret
star:
mov [char], byte '*';
push rax;
push rbx;
mov eax,4; ;sys_write
mov ebx,1; ;stdout
mov ecx, char;
mov edx,1;
int 80h;
pop rbx;
pop rax;
ret
down_triangle:
push rax;
push rbx;
mov rax, [trianglerows]
inc ax
mov [trianglerows],rax
pop rbx
pop rax
ret
我嘗試過並試過但我無法得到我需要的東西。
我似乎無法找到將行與星線分開的方法,因為所有那些push
和pop
。
老實說,我不太了解這些。 我被告知他們需要執行循環,但我不知道為什么,例如,函數star
我需要調用外循環。
我找不到push
和pop
任何組合。 我不斷獲得許多星星或每行一顆星或只有一顆星。
我真的很困惑,我正在改變哪些位並保持不變。 我能夠獲得所需的輸出,但一個從未結束增加。
我能夠從10顆星開始輸出,然后降到1,但絕不是我想要的。
我究竟做錯了什么? 我該怎么做這個問題?
你的第一行有10顆星,因為你在你的內環中使用[trianglerows]
。 我確定你打算使用[trianglesize]
(目前你沒有在任何地方使用)。 然后在down_triangle
,你將再次增加[trianglesize]
而不是[trianglerows]
。 最后,您可能希望[trianglesize]
以1而不是0開頭,對於第一行中的1個星。
此外,請務必按照下面的評論中的Michael Petch所述更正您的內存使用情況,否則您的變量會因為它們共享相同的內存而被損壞。
我用這種方式解決了問題,它是32位:
bits 32
global _start
section .data
rows dw 10
section .text
_start:
movzx ebx, word [rows] ; ebx holds number of rows, used in loop
; here we count how many symbols we have
lea eax, [ebx+3]
imul eax,ebx
shr eax,1 ; shr is used to divide by two
; now eax holds number of all symbols
mov edx, eax ; now edx holds number of all symbols, used in print
;we prepare stack to fill data
mov ecx,esp
sub esp,edx
;we fill stack backwards
next_line:
dec ecx
mov [ecx],byte 10
mov eax,ebx
next_star:
dec ecx
mov [ecx],byte '*'
dec eax
jg next_star
dec ebx
jg next_line
;print ; edx has number of chars; ecx is pointer on the string
mov eax,4; ;sys_write
inc ebx; ;1 - stdout, at the end of the loop we have ebx=0
int 80h;
;exit
mov eax,1 ;1 - sys_exit
xor ebx,ebx ;0 - return 0
int 80h;
ret
我是怎么做到的?
首先,我計算我們要打印的符號數。 我馬上打印出來。 它是有限算術級數 (算術級數)的總和。
在我們的例子中,我們有
我們看到3個操作+
, *
和/
。 我們只能將除法優化為2,做右移:
lea eax, [ebx+3] ; n + 3
imul eax,ebx ; n * (n + 3)
shr eax,1 ; n * (n+3) / 2
我們的字符串將在堆棧中,讓我們准備它有足夠的內存:
mov ecx,esp
sub esp,edx
然后,我們用星星和\\n
填充我們的堆棧
next_line:
dec ecx
mov [ecx],byte 10
mov eax,ebx
next_star:
dec ecx
mov [ecx],byte '*'
dec eax
jg next_star
dec ebx
jg next_line
我向后填補它。 這是什么意思? 我用符號從結尾到開頭填充字符串。 為什么我這樣做? 僅僅因為我想盡可能少地使用寄存器。 在循環結束時, ecx
在字符串上包含一個我們想要打印的指針。 如果我向前填充, ecx
在“堆棧准備”之前在esp
上包含一個指針,並且我不能將該寄存器用作print
函數中字符串的指針。 此外,我必須使用另一個寄存器來減少或使用比dec
慢的cmp
。
這就是全部,打印和結束。
另一個案例
global _start
section .data
rows dw 10
section .text
_start:
;it defines how many symbols we have to print
movzx ebx, byte[rows] ; ebx holds number of rows
lea eax,[ebx+3]
imul eax,ebx
shr eax,1 ; now eax holds number of all symbols
mov edx,eax ; now edx holds number of all symbols, used in print
;prepare pointer
mov ecx,esp
sub ecx,eax ; ecx points on the beginning of the string, used in print
;fill the string by stars
mov eax,edx
shr eax,2
mov ebp, dword '****'
next_star:
mov [ecx+4*eax],ebp
dec eax
jge next_star
;fill the string by '\n'
mov edi,esp
dec edi
mov eax,ebx; in the eax is number of rows
inc eax
next_n:
mov [edi],byte 0xa
sub edi,eax
dec eax
jg next_n
;print
;mov ecx,esp
mov eax,4; ;sys_write
mov ebx,1; ;1 - stdout
int 80h;
;exit
mov eax,1 ;1 - sys_exit
xor ebx,ebx ;0 - return 0
int 80h;
ret
在這里,我們在開始時用星星填充堆棧,然后我們用\\n
s填充它
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.