We want to iterate through our loop, but we don't want to manually step through every instruction over and over again.
We can automate this process by using another script. First, we will set a break point at the end of our loop with:
The * character lets gdb know that the value is a memory address and not a label name.
Enter:
To skip down to our break point. Now we can write our script. Enter:
We just wrote a while loop to debug our while loop.
Your output should be similar to this (note you may have to enter ctrl + l to re-draw your screen):
(gdb) break *0x100c0 Breakpoint 1 at 0x100c0
Enter:
continue
(gdb) set $count = 0 (gdb) while $count < 8 >source cpsr_cmp.gdb >continue >set $count = $count +1 >end
Your output should be similar to this (note you may have to enter ctrl + l to re-draw your screen):
|-Register group: general------------------------------------------------------------------------------------------------------------------------------------------------|
|r0 0x2 2 r1 0x408009bc 1082132924 |
|r2 0x2 2 r3 0x9 9 |
|r4 0x0 0 r5 0x0 0 |
|r6 0x0 0 r7 0x4 4 |
|r8 0x0 0 r9 0x0 0 |
|r10 0x200ec 131308 r11 0x0 0 |
|r12 0x0 0 sp 0x408009c0 0x408009c0 |
|lr 0x0 0 pc 0x100c0 0x100c0 <print_counter+52> |
|cpsr 0x80000010 -2147483632 fpscr 0x0 0 |
|fpsid 0x410430f0 1090793712 fpexc 0x40000000 1073741824 |
|AFSR0_EL1 0x0 0 AFSR1_EL1 0x0 0 |
|DBGDIDR 0x3515f021 890630177 DBGDSAR 0x0 0 |
|DBGBVR 0x0 0 DBGBCR 0x0 0 |
|DBGWVR 0x0 0 DBGWCR 0x0 0 |
|PAR 0x0 0 DBGBVR 0x0 0 |
|DBGBCR 0x0 0 DBGWVR 0x0 0 |
|DBGWCR 0x0 0 TEECR 0x0 0 |
|MIDR_EL1 0x412fc0f1 1093648625 CTR 0x8444c004 -2075869180 |
|TCMTR 0x0 0 TTBR0_EL1 0x0 0 |
|------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 0x10098 <print_counter+12> add r1, r1, r3 |
| 0x1009c <print_counter+16> orr r1, r1, #2560 ; 0xa00 |
| 0x100a0 <print_counter+20> push {r1} ; (str r1, [sp, #-4]!) |
| 0x100a4 <print_counter+24> mov r1, sp |
| 0x100a8 <print_counter+28> mov r2, #2 |
| 0x100ac <print_counter+32> svc 0x00000000 |
| 0x100b0 <print_counter+36> add sp, sp, #4 |
| 0x100b4 <print_counter+40> cmp r3, #9 |
| 0x100b8 <print_counter+44> bge 0x100c4 <print_end_msg> |
| 0x100bc <print_counter+48> add r3, r3, #1 |
|B+> 0x100c0 <print_counter+52> b 0x1008c <print_counter> |
| 0x100c4 <print_end_msg> mov r7, #4 |
| 0x100c8 <print_end_msg+4> mov r0, #1 |
| 0x100cc <print_end_msg+8> ldr r1, [pc, #20] ; 0x100e8 <exit_normally+16> |
| 0x100d0 <print_end_msg+12> mov r2, #12 |
| 0x100d4 <print_end_msg+16> svc 0x00000000 |
| 0x100d8 <exit_normally> mov r7, #1 |
| 0x100dc <exit_normally+4> mov r0, #0 |
| 0x100e0 <exit_normally+8> svc 0x00000000 |
| 0x100e4 <exit_normally+12> andeq r0, r2, r12, ror #1 |
|------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
remote Thread 1.39901 In: print_counter L?? PC: 0x100c0
N=1 Z=0 C=0 V=0
Breakpoint 1, 0x000100c0 in print_counter ()
N=1 Z=0 C=0 V=0
Breakpoint 1, 0x000100c0 in print_counter ()
N=1 Z=0 C=0 V=0
Breakpoint 1, 0x000100c0 in print_counter ()
N=1 Z=0 C=0 V=0
Breakpoint 1, 0x000100c0 in print_counter ()
N=1 Z=0 C=0 V=0
Breakpoint 1, 0x000100c0 in print_counter ()
N=1 Z=0 C=0 V=0
Breakpoint 1, 0x000100c0 in print_counter ()
N=1 Z=0 C=0 V=0
Breakpoint 1, 0x000100c0 in print_counter ()
(gdb)
Notice we are now on what should be the last iteration of the loop.
Let's advance to the bge instruction with:
Let's look at what flags were set with our cmp instruction:
Notice that the zero bit is now set and the negative bit is no longer set.
The zero bit is set because r3 was equal to 9. The negative bit is not set because the result of 9 - 9 isn't negative. Both of these condititions should cause our branch condition to be met.
Let's test this branch by setting a break point where we should jump to:
advance *0x100b8
(gdb) source cpsr_cmp.gdb N=0 Z=1 C=1 V=0
The zero bit is set because r3 was equal to 9. The negative bit is not set because the result of 9 - 9 isn't negative. Both of these condititions should cause our branch condition to be met.
Let's test this branch by setting a break point where we should jump to:
(gdb) break *0x100c4 Breakpoint 2 at 0x100c4
Enter continue to advance the program to the next break:
|------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 0x1008c <print_counter> mov r7, #4 |
| 0x10090 <print_counter+4> mov r0, #1 |
| 0x10094 <print_counter+8> mov r1, #48 ; 0x30 |
| 0x10098 <print_counter+12> add r1, r1, r3 |
| 0x1009c <print_counter+16> orr r1, r1, #2560 ; 0xa00 |
| 0x100a0 <print_counter+20> push {r1} ; (str r1, [sp, #-4]!) |
| 0x100a4 <print_counter+24> mov r1, sp |
| 0x100a8 <print_counter+28> mov r2, #2 |
| 0x100ac <print_counter+32> svc 0x00000000 |
| 0x100b0 <print_counter+36> add sp, sp, #4 |
| 0x100b4 <print_counter+40> cmp r3, #9 |
| 0x100b8 <print_counter+44> bge 0x100c4 <print_end_msg> |
| 0x100bc <print_counter+48> add r3, r3, #1 |
|B+ 0x100c0 <print_counter+52> b 0x1008c <print_counter> |
|B+> 0x100c4 <print_end_msg> mov r7, #4 |
| 0x100c8 <print_end_msg+4> mov r0, #1 |
| 0x100cc <print_end_msg+8> ldr r1, [pc, #20] ; 0x100e8 <exit_normally+16> |
| 0x100d0 <print_end_msg+12> mov r2, #12 |
| 0x100d4 <print_end_msg+16> svc 0x00000000 |
| 0x100d8 <exit_normally> mov r7, #1 |
|------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
remote Thread 1.40929 In: print_end_msg L?? PC: 0x100c4
N=1 Z=0 C=0 V=0
Breakpoint 1, 0x000100c0 in print_counter ()
N=1 Z=0 C=0 V=0
Breakpoint 1, 0x000100c0 in print_counter ()
N=1 Z=0 C=0 V=0
Breakpoint 1, 0x000100c0 in print_counter ()
(gdb) si
0x0001008c in print_counter ()
(gdb) advance *0x100b8
0x000100b8 in print_counter ()
(gdb) source cpsr_cmp.gdb
N=0 Z=1 C=1 V=0
(gdb) break *0x100c4
Breakpoint 2 at 0x100c4
(gdb) continue
Continuing.
Breakpoint 2, 0x000100c4 in print_end_msg ()
(gdb)
Notice that our program had two breakpoints set, one at 0x100c0 which would branch back to the start of our loop,
and another at 0x100c4 which will continue the rest of the program.
Our condition to branch was met by both the zero bit being set to 1 and the negative bit being set to 0, so execution moved to 0x100c4.
Enter continue one last time to finish executing the remainder of the program:
Enter continue one last time to finish executing the remainder of the program:
(gdb) continue Continuing. [Inferior 1 (process 1) exited normally] (gdb)