簡體   English   中英

如何在裝配中打印三角形的星星?

[英]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

我嘗試過並試過但我無法得到我需要的東西。

我似乎無法找到將行與星線分開的方法,因為所有那些pushpop

老實說,我不太了解這些。 我被告知他們需要執行循環,但我不知道為什么,例如,函數star我需要調用外循環。

我找不到pushpop任何組合。 我不斷獲得許多星星或每行一顆星或只有一顆星。

我真的很困惑,我正在改變哪些位並保持不變。 我能夠獲得所需的輸出,但一個從未結束增加。

我能夠從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

我是怎么做到的?
首先,我計算我們要打印的符號數。 我馬上打印出來。 它是有限算術級數 (算術級數)的總和。

TriangleImage

在我們的例子中,我們有

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填充我們的堆棧

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填充它

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM