Question

I have a project where I want to enter a number and say I enter 3, it gives you an output of,

ZYX**XYZ

ZY****YZ

Z******Z

And a 5 will give you

ZYXWV**VWXYZ

ZYXW****WXYZ

ZYX******XYZ

ZY********YZ

Z**********Z

In my project I don't think my instructor will allow me to use an array, or at least not yet but here is my idea.

I was thinking of making a string for the number so say I get a 3. I would produce ZYX* and simply reverse it to get the other half of the triangle. Only thing is, I don't know how to change the letters one at a time to the stars. I'm thinking of using loops to do it but not sure how to do it. I just know that the next string would be ZY** and then simply reverse it.

Don't get me wrong, I'm not asking you all to do it for me but maybe give me some pointers or tips on how to approach it. thank you.

So far, thanks to you all, I have been able to come up with this.

TITLE MASM Template                     (main.asm)

; Description:
; 
; Revision date:

INCLUDE Irvine32.inc

.data
x       DWORD   ?
msg     BYTE    "Please input a number: " ,0dh,0ah,0

.code
;crlf
main PROC
    call    Clrscr

    MOV     edx, OFFSET msg         ; Moves message to input number into register
    call    WriteString         ; Displays message on screen to prompt user to input number
    call    readInt             ; Take the number that the user inputs
    MOV     x,eax                   ; Store it into x
    MOV     ecx, eax                ; For the loop counter  
    MOV     al, 'Z'                 ; Move Z to the register

L2:
    MOV     al, 'Z'             ; Resets al to z for loop

L1:                         ; Start of the loop with label L1
    call    WriteChar           ; To write the letters
    ;call crlf              ; To put in 'enter'
    SUB     al, 1               ; To Move the next char going downward
    LOOP    L1

    MOV     al, ' '
    call    WriteChar
    MOV     ecx, x                  ; Resets ecx for outside loop
    SUB     x, 1                    ; Decrements x for counter

    call    crlf                    ; To be tidy    
    LOOP    L2

    exit
main ENDP
END main

Now I just need the other side.

Was it helpful?

Solution

Welcome to the blackest of the black computer arts - Assembler!

Let's look at this problem from an Assembler programmer's point of view.

You have a number, let's say BL ('cause that's a good Assemblerish name) and what you want to do is produce BL lines of output. Let's say BL=5

Now, CX is really good as a counter register, so if we copy BL to CL and clear CH by XORing it with itself, we have CX=#lines too.

The number of characters we have to print before reversing is conveniently one more than this, so we could increment CX - and that's an important number, so save it in say, BP

Each line consists of the letters 'Z' down to ('Z' - BH + 1) and one asterisk, then the same in reverse, and a new line. And every new line, you reduce the number of letters printed by one and add one to the number of asterisks.

To produce one line, we'd

  • Load a register - say, DL, with 'Z' (DL because it's convenient as the output for a 'printme' routine)
  • Copy that to another register, say BH (a register-to-register move is faster and smaller than a load-immediate)
  • Subtract BL from BH, yielding a magic value, 'Z' - 5 = 'U' - is there a bell ringing yet?

We want to print a count of letters, so if we copy BP into CX, that should be useful.
Here's something we want to do CX times:

  • Write out the character in DL - with a twist.
  • Change the character in DL by DECREMENTING it

Then we need to output another BP bytes, so sopy BP to CX again
Here's something we want to do CX times:

  • Write out the character in DL - with a twist.
  • Change the character in DL by INCREMENTING it

Then send CR and LF

So - what's the twist?

Well, if the character in DL is LESS THAN or EQUAL TO the character in BH, we want to substitute an asterisk, so

  • save DX on the stack
  • load DL with ASTERISK if DL<=BH
  • output DL
  • pop DX back from the stack, restoring its value before we substituted the asterisk.

Done that line - decrement the count of lines in BL; if the result is non-zero, produce another line

  • If it is zero, we're all done.

Note here that by decrementing the count of lines in BL, the number subtracted from DL at the start of the produce-a-line routine decrements, so the 'change to aster' value becomes 'V', 'W'...

Now let's get downright kinky.

You'll note that the only difference between the two write-CX-characters routines is that one DECREMENTS and the other INCREMENTS DL...

Let's set SI to 0FFFFH and DI to 1 before we start, just for laughs.

Now - DH is sitting on the bench for this entire game.

Suppose we write the routine to print CX characters such that it ADDs SI to DX. That will give us the decrement we need in the loop the first time.

  • When the loop ends, suppose we EXCHANGE DI and SI.
  • The next time the loop runs, it will INCREMENT DX, then exchange SI and DI again.

Useful, huh?

Oh, and while we're twisting, we can get DH involved by using it to store DL rather than pushing DX and popping it back. Move DL to DH, test for substituting the aster, write out and restore DL from DH.

So - the point with this routine is that it doesn't rely on a string in storage...

OTHER TIPS

I wrote a tutorial on how to create a pyramid of characters. It uses NASM and the Windows API instead of Irvine, but the tutorial should get you going and help you a bit on the logistics.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top