☀️ 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