I need to get the following output:
*
**
***
****
*****
******
*******
********
*********
**********
So its 10 rows,and my stars will start at 1 and go to 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
.
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.
I couldn't find any combination of push
and pop
that worked. 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.
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. I'm sure you intended to use [trianglesize]
(which currently you aren't using anywhere). Then in down_triangle
, you'll want to increment, again, [trianglesize]
rather than [trianglerows]
. Finally, you probably want [trianglesize]
to start with 1 rather than 0, for 1 star in the first row.
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.
I solved the problem this way, it's 32-bit:
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 /
. We can optimise only the division by 2, doing right shift:
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
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. 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. Also I have to use another register to decrement or use cmp
which is slower than dec
.
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
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.