![](/img/trans.png)
[英]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.