我需要获得以下输出:
*
**
***
****
*****
******
*******
********
*********
**********
所以它的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,但从来没有我想要的。
我做错了什么?我该怎么做这个问题?
答案 0 :(得分:4)
您的第一行有10颗星,因为您在内循环中使用[trianglerows]
。我确定你打算使用[trianglesize]
(目前你没有在任何地方使用)。然后在down_triangle
中,您需要再次增加[trianglesize]
而不是[trianglerows]
。最后,您可能希望[trianglesize]
以1而不是0开头,第一行中的1星。
此外,请务必按照下面的评论中的Michael Petch所述更正您的内存使用情况,否则您的变量会因为共享相同内存而损坏。
答案 1 :(得分:2)
我用这种方式解决了问题,它是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
我是怎么做到的?
首先,我计算我们要打印的符号数。我马上把它打印出来。它是有限arithmetic progression(算术系列)的总和。
在我们的案例中,我们有
我们看到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
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
我向后填补它。这是什么意思?我用符号从结尾到开头填充字符串。为什么我这样做?仅仅因为我想尽可能少地使用寄存器。在循环结束时ecx
在字符串上包含一个我们想要打印的指针。如果我向前填充,ecx
在&{34;堆栈准备"之前在esp
上包含一个指针,我就不能将该寄存器用作{{1}中字符串的指针功能。另外,我必须使用另一个寄存器来递减或使用慢于print
的{{1}}。
全部,打印和结束。
另一个案例
cmp
在这里,我们在开始时用星星填充堆栈,然后我们用dec
s填充它