如何将角色推入新线?

时间:2017-03-01 19:43:31

标签: assembly nasm

我正在尝试创建一个代码,我会在其中获取用户输入,将其转换为循环并显示三角形。

    ;; using a nested loop create a triangle
section .data
        global _start
        prompt db "Enter number of lines you'd like: ",10 ;;declare constant string that  points to ’string’ 10 equates to the line character
        promptLen equ $-prompt ;; This returns the length of the string
        char db ' ' ; declare char to store asterisks and newlines
segment .bss
    num1 resb 1
section .text
_start:
        mov eax,4 ;; Move the system call 4 to the register eax to say ouput
        mov ebx,1 ;;  put the value 1 in the register ebx - standard output to the screen
        mov ecx, prompt ; Put the offset of string in ecx register so we can access the string and the new line character
        mov edx, promptLen ;; put the length of the string into the register
        int 80h ; Call the operating system with an interrupt. The operating system checks the registers and performs the operation to write to screen
        mov eax,3 ; system call input
        mov ebx, 0 ; stand input
        mov ecx, num1 ; store inputted value in num1 - note ascii value and should be between 1-9
        mov edx, 1 ; size of input value in bytes
        int 80h ; call kernel with interrupt to receive value
        mov rax, [num1] ; move value in num1 into rax
        sub rax, 48; subtract 48 from value so now it is integer and not ascii value
        mov [num1], rax ; move value back into num1 use ax for the row counter
        mov rax, [num1]; move num1 into rax to set the size of the outer loop - rows of triangle
        outer_loop: ; use ax for the row counter
                mov rbx, [num1] ; move num1 into rbx to set the size of the inner loop
                inner_loop: ;; draw a asterisk
                        call asterisk ;; subtract from the counter and repeat if we haven't hit 0 for inner loop
                        dec bx
                        cmp bx,0
                        jg inner_loop ;; go on to next line
                call linefeed ; subtract from the counter and repeat if we haven't hit 0 for outer loop
                dec ax
                cmp ax,0
                jne outer_loop  ;; go to next line
                call linefeed ;; exit cleanly

exit:
        mov eax,1; system call to exit
        mov ebx,0; exit value
        int 80h; call kernel with interrupt to exit program
        ret;; new line code section

linefeed:
        ;; move newline character into char
        mov [char],  byte 10
        push rax; push rax on to stack to allow outer loop to 
                ; occur
        push rbx; push rbx on to stack to allow inner loop to 
            ; occur
        mov eax,4; system call to write out
        mov ebx,1; standard out to screen
        mov ecx, char; go to next line on screen
        mov edx,1; size of new line
        int 80h; interrupt to kernel to go to next line by 
            ; looking into registers
        pop rbx; push rax on to stack to allow outer loop to 
            ; occur
        pop rax; push rbx on to stack to allow inner loop to 
            ; occur
        ret

asterisk:

        mov [char],  byte '*'; put asterisk (*) in char
        push rax; push rax on to stack to allow outer loop to occur
        push rbx; push rbx on to stack to allow inner loop to occur
        mov eax,4; system call to write out
        mov ebx,1; standard out to screen
        mov ecx, char; put asterisk in register ecx
        mov edx,1; size of asterisk in register
        int 80h; interrupt to kernel to print asterisk on screen by looking into registers
        pop rbx
        pop rax

        ret

是的,我知道它不干净,但我正在努力学习如何为新行添加角色。

最终结果看起来应该更像这样。

  • (1星号)

**(在新行中按星号)

***(在另一个新行中按星号然后依此类推)

如何在循环中使用push命令执行此操作?

1 个答案:

答案 0 :(得分:0)

同时我会解决这个问题:

break

这是32位x86程序集,要编译+运行,将其保存到 ; NOT using a nested loop create a triangle ; rather using line buffer to buffer the I/O operations to make it faster section .data prompt db "Enter number of lines you'd like: ",10 promptLen equ $-prompt ;; This returns the length of the string section .bss linebuffer resb 100 section .text global _start _start: mov eax,4 mov ebx,1 mov ecx, prompt mov edx, promptLen int 80h ; sys_write(STD_OUT, prompt, promptLen) mov eax,3 xor ebx,ebx mov ecx,linebuffer ; reusing future linebuffer also for user input mov edx,1 int 80h ; sys_read(STD_IN, linebuffer, 1) ; linebuffer now contains single ASCII character from user -> size movzx esi,byte [linebuffer] sub esi,'0' ; esi = size of pyramid ; init values for line-loop, first data-like things mov edi,linebuffer ; address where next asterisk should be written mov edx,1 ; number of chars to be displayed (line size) (1 = new line) ; init fixed values for outputting lines through "int 80h" mov ebx,1 ; STD_OUT mov ecx,linebuffer ; address of linebuffer pyramid_loop: cmp edx,esi ; already big enough line printed? ja pyramid_done ; prepare line buffer by adding another asterisk, and increment line size mov [edi],word `*\n` ; does also add new <new line> char at end inc edi ; update address to write next asterisk inc edx ; increase size of current line (line size) ; display the prepared line buffer mov eax,4 ; sys_write (has to be set again, sys_write return value modifies it) int 80h ; sys_write(STD_OUT, linebuffer, "line size") jmp pyramid_loop pyramid_done: mov eax,1 ; system call to exit xor ebx,ebx ; 0 exit code int 80h

ppp.asm

我留下了一些关于特定指令的注释,但是你应该能够自己解释它的工作原理,或者在循环期间观察调试器中内存内容的变化。