3

我需要得到以下输出:

*
**
***
****
*****
******
*******
********
*********
**********

所以它有 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

我尝试了又尝试了,但我无法得到我需要得到的东西。

由于所有这些pushpop.

老实说,我不太了解这些。我被告知执行循环需要它们,但我不确定为什么,例如,在函数中star我需要调用外部循环。

我找不到任何有效push的组合pop。我经常得到很多星或每行一颗星或只有一颗星。

我真的很困惑我正在改变哪些位并保持不变。我能够获得所需的输出,但输出永远不会增加。

我能够得到从 10 颗星开始下降到 1 颗星的输出,但从来都不是我想要的。

我究竟做错了什么?我该怎么做这个问题?

4

2 回答 2

5

您的第一行有 10 颗星,因为您[trianglerows]在内部循环中使用。我确定您打算使用[trianglesize](目前您没有在任何地方使用)。然后在 中down_triangle,您将希望再次增加,[trianglesize]而不是[trianglerows]. 最后,您可能希望[trianglesize]从 1 而不是 0 开始,因为第一行中有 1 颗星。

此外,请务必按照 Michael Petch 在下面评论中的描述更正您的内存使用情况,否则您的变量将被损坏,因为它们共享相同的内存。

于 2018-03-17T23:31:42.257 回答
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

我是怎么做到的?
首先,我计算我们必须打印的符号数量。我会一次性打印出来。它是有限算术级数(算术级数)的总和。

三角形图像

在我们的例子中,我们有

a1=2andd=1

锡

我们看到 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包含一个指针esp,并且我不能将寄存器用作print函数中字符串的指针。另外我必须使用另一个寄存器来减少或使用cmpdec.

就是这样,打印并结束。


另一个案例

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

在这里,一开始我们用星号填充堆栈,然后才用\ns填充它

https://github.com/tigertv/stackoverflow-answers

于 2018-03-18T08:54:55.850 回答