[英]How to print a triangle of stars in assembly?
I need to get the following output: 我需要获得以下输出:
*
**
***
****
*****
******
*******
********
*********
**********
So its 10 rows,and my stars will start at 1 and go to 10. 所以它的10行,我的星星将从1开始,然后到10。
Currently I am getting: 目前我得到:
**********
***********
************
*************
**************
***************
****************
*****************
******************
*******************
********************
My code: 我的代码:
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
I tried and tried and tried but I couldn't get what I needed to get. 我尝试过并试过但我无法得到我需要的东西。
I seem to be unable to find a way to separate the rows from the lines of stars, because of all those push
and pop
. 我似乎无法找到将行与星线分开的方法,因为所有那些
push
和pop
。
Honestly, I do not understand these much. 老实说,我不太了解这些。 I've been told that they are needed to execute the loops, but I am not sure why, for example, in the function
star
I would need to call the outer loop. 我被告知他们需要执行循环,但我不知道为什么,例如,函数
star
我需要调用外循环。
I couldn't find any combination of push
and pop
that worked. 我找不到
push
和pop
任何组合。 I am constantly getting either many stars or one star per line or just one star. 我不断获得许多星星或每行一颗星或只有一颗星。
I am literally puzzled at which bits I'm changing and keeping the same. 我真的很困惑,我正在改变哪些位并保持不变。 I was able to get the required output but one that never ended increasing.
我能够获得所需的输出,但一个从未结束增加。
I was able to get output starting from 10 stars and going down to one, but never what I wanted. 我能够从10颗星开始输出,然后降到1,但绝不是我想要的。
What am I doing wrong? 我究竟做错了什么? How do I do this question?
我该怎么做这个问题?
Your first row has 10 stars because you are using [trianglerows]
in your inner loop. 你的第一行有10颗星,因为你在你的内环中使用
[trianglerows]
。 I'm sure you intended to use [trianglesize]
(which currently you aren't using anywhere). 我确定你打算使用
[trianglesize]
(目前你没有在任何地方使用)。 Then in down_triangle
, you'll want to increment, again, [trianglesize]
rather than [trianglerows]
. 然后在
down_triangle
,你将再次增加[trianglesize]
而不是[trianglerows]
。 Finally, you probably want [trianglesize]
to start with 1 rather than 0, for 1 star in the first row. 最后,您可能希望
[trianglesize]
以1而不是0开头,对于第一行中的1个星。
Also, be sure to correct your memory usage as described by Michael Petch in the comments below, otherwise your variables are being corrupted because they share the same memory. 此外,请务必按照下面的评论中的Michael Petch所述更正您的内存使用情况,否则您的变量会因为它们共享相同的内存而被损坏。
I solved the problem this way, it's 32-bit: 我用这种方式解决了问题,它是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
How did I do it? 我是怎么做到的?
First of all, I count number of symbols what we have to print. 首先,我计算我们要打印的符号数。 I'll print it all at once.
我马上打印出来。 It's the sum of a finite arithmetic progression (arithmetic series).
它是有限算术级数 (算术级数)的总和。
In our case we have 在我们的例子中,我们有
We see 3 operations +
, *
and /
. 我们看到3个操作
+
, *
和/
。 We can optimise only the division by 2, doing right shift: 我们只能将除法优化为2,做右移:
lea eax, [ebx+3] ; n + 3
imul eax,ebx ; n * (n + 3)
shr eax,1 ; n * (n+3) / 2
Our string will be on the stack, let's prepare it to have enough memory: 我们的字符串将在堆栈中,让我们准备它有足够的内存:
mov ecx,esp
sub esp,edx
And then, we fill our stack by stars and \\n
s 然后,我们用星星和
\\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
I fill it backwards. 我向后填补它。 What does it mean?
这是什么意思? I fill the string by symbols from the end to the beginning.
我用符号从结尾到开头填充字符串。 Why do I do that?
为什么我这样做? Just because I want to use less registers as it possible.
仅仅因为我想尽可能少地使用寄存器。 At the end of the loop
ecx
contains a pointer on the string what we want to print. 在循环结束时,
ecx
在字符串上包含一个我们想要打印的指针。 If I filled forwards, ecx
contains a pointer on esp
before "stack prepairing", and I can't use the register as a pointer on string in print
function. 如果我向前填充,
ecx
在“堆栈准备”之前在esp
上包含一个指针,并且我不能将该寄存器用作print
函数中字符串的指针。 Also I have to use another register to decrement or use cmp
which is slower than dec
. 此外,我必须使用另一个寄存器来减少或使用比
dec
慢的cmp
。
That's all, print and end. 这就是全部,打印和结束。
Another case 另一个案例
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
Here, at the beginning we fill the stack by stars and only after that we fill it by \\n
s 在这里,我们在开始时用星星填充堆栈,然后我们用
\\n
s填充它
https://github.com/tigertv/stackoverflow-answers https://github.com/tigertv/stackoverflow-answers
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.