[ARM assembly] print pyramid | print inverted triangle


Each Preface

☀️ Hello, I'm Tom Kate. You can call me Tom
🐋 Personal homepage: IM Tom Kate's CSDN blog
🎁 Series column: [ARM embedded foundation]
🌱 Daily sentence:

No one is omniscient. What knowledge can really bring us is that we are not afraid of the unknown.

Write before:

After learning the loop and branch statements of assembly, let's do a small exercise. How to print a pyramid with a loop? How to print an inverted triangle? The following points need to be explained and realized.

How to print pyramids?

design sketch:

1) Determine format string

🍎 As shown in the figure, it can be seen that the contents of the printout include "space", "*" and "line feed", so the format string of the printout needs to be defined first.

.data
    str:.asciz " "
    str1:.asciz "*"
    crlf:.asciz "\n"

2) Pseudo code

🍏 The design of the whole program includes a larger number of cycle control layers, and two internal cycles control whether to print out "space" or "*".

3) Building a large cycle framework

🍊 Because the implementation requirements are relatively simple, only printing is required, and no input and other operations are required, the number of layers of the cycle can be defined in advance.

🍋 Each line of r4+1 is executed. When the number of executions exceeds 8 and LS is not satisfied, the jump is not carried out and the program ends.

.data
    str:.asciz " "
    str1:.asciz "*"
    crlf:.asciz "\n"
    .equ n,8  //Number of layers of pyramid
.text
.globl main
 main:
    push {lr}
    ldr r0,=crlf   //Leave the first line blank
    bl printf 
    mov r4,#1 / / R4 control variable of storage layer cycle
    b for1
l1: 
	......
	add r4,#1
for1:
    cmp r4,#n
    bls l1   //ls unsigned number less than or equal to

    mov r0,#0
    pop {lr}
    mov pc,lr 
.end

4) Build two small loops

There are only two modes of printing "space" and "*" for each line, so two loops need to be built.

The key to the cycle is the number of cycles and the content to be executed. The number of "spaces" and "*" to be printed in each line is different, so the number of cycles is the key.

🍒 Looking at the above picture, we can see that the * sign satisfies a law "n" × 2-1 ", n indicates the number of layers. So we can express it in two lines of instructions

    mov r5,r4,lsl#1 / / shift the logic to the left, which is equivalent to r4*2, and then pass it to r5
    sub r5,#1

🍇 It can also be found that the number of spaces to be printed in each line is successively reduced by 1, so we can first attach an initial value s=20 to the empty line, and then make this cycle into an s-1 cycle, but we need to fix the number of layers of the cycle, so we can directly let s-r4, R4 is the number of layers of each layer.

    rsb r5,r4,#s / / reverse subtraction instruction

🍉 This solves the problem of the number of two cycles. The code of the internal loop is as follows:

l1: 
    rsb r5,r4,#s   
    b for2
l21:
    ldr r0,=str 
    bl printf
    sub r5,#1
for2:
    cmp r5,#0
    bhi l21
    mov r5,r4,lsl#1  
    sub r5,#1
    b for3
l22:
    ldr r0,=str1    
    bl printf
    sub r5,#1
for3:
    cmp r5,#0
    bhi l22
    ldr r0,=crlf 
    bl printf
    add r4,#1

How to print inverted triangle with assembly?

With the core idea of printing pyramid unchanged, the overall framework remains unchanged. The change is that the number of "spaces" and "*" needs to be printed is different. The following points need to be changed.

Change one

🍑 R4 needs to be initialized before s-r4. The initial value of R4 must be the maximum value, that is, the number of layers n

    mov r4,#n

Change II

🍈 Starting from the maximum value, it can't be an increasing cycle. It needs to be changed into a decreasing cycle

    sub r4,#1

Transformation three

🍌 In the control statement of stopping the loop, it needs to be changed to keep the loop when the value of r4 is greater than 0, and HI indicates that the unsigned number is greater than.

    cmp r4,#0   //You must use 0, not 1, because the following is greater than. If you use #1, r4 will end directly after it is reduced to 1, and the last time is not executed.
    bhi l1

Print the whole assembly code of inverted triangle

.data
    str:.asciz " "
    str1:.asciz "*"
    crlf:.asciz "\n"
    .equ n,8
    .equ s,20
.text
.globl main
 main:
    push {lr}
    ldr r0,=crlf 
    bl printf 
    mov r4,#n
    b for1
l1: 
    rsb r5,r4,#s / / reverse subtraction instruction
    b for2
l21:
    ldr r0,=str 
    bl printf
    sub r5,#1
for2:
    cmp r5,#0
    bhi l21
    mov r5,r4,lsl#1 / / shift the logic to the left, which is equivalent to r4*2, and then pass it to r5
    sub r5,#1
    b for3
l22:
    ldr r0,=str1    
    bl printf
    sub r5,#1
for3:
    cmp r5,#0
    bhi l22
    ldr r0,=crlf 
    bl printf
    sub r4,#1
for1:
    cmp r4,#0   //You must use 0, not 1, because the following is greater than. If you use #1, r4 will end directly after it is reduced to 1, and the last time is not executed.
    bhi l1

    mov r0,#0
    pop {lr}
    mov pc,lr 
.end

The results show that:

This issue is over. If it's helpful to you, please click like + comment to support the blogger before you go I haven't paid attention to Tom's friends yet. I'll learn some compilation every day Forecast for next period: Factorial solution of ARM assembly n

Tags: Embedded system ARM

Posted by zildjohn01 on Thu, 19 May 2022 02:53:36 +0300