Hey so here is just a simple program i wrote in c, compiled under avr-gcc.. The corresponding assembly code is posted too.
Still cant understand what the assembly code for the switch statement is doing, any help would be great. thanks.
int main()
{
char myinput;
printf("Which option will you choose:\n");
printf("a) Program 1 \n");
printf("b) Program 2 \n");
scanf("%c", &myinput);
switch (myinput)
{
case 'a':
printf("Run program 1\n");
break;
case 'b':
{
printf("Run program 2\n");
printf("Please Wait\n");
break;
}
default:
printf("Invalid choice\n");
break;
}
return 0;
return 0;
}
Assembly Code:
switch (myinput)
+00000147: 900F POP R0 Pop register from stack
+00000148: 900F POP R0 Pop register from stack
+00000149: 900F POP R0 Pop register from stack
+0000014A: 900F POP R0 Pop register from stack
+0000014B: 8189 LDD R24,Y+1 Load indirect with displacement
+0000014C: 3681 CPI R24,0x61 Compare with immediate
+0000014D: F019 BREQ PC+0x04 Branch if equal
+0000014E: 3682 CPI R24,0x62 Compare with immediate
+0000014F: F459 BRNE PC+0x0C Branch if not equal
+00000150: C003 RJMP PC+0x0004 Relative jump
22: printf("Run program 1\n");
+00000151: E38D LDI R24,0x3D Load immediate
+00000152: E092 LDI R25,0x02 Load immediate
+00000153: C009 RJMP PC+0x000A Relative jump
26: printf("Run program 2\n");
+00000154: E48B LDI R24,0x4B Load immediate
+00000155: E092 LDI R25,0x02 Load immediate
+00000156: 940E02A9 CALL 0x000002A9 Call subroutine
27: printf("Please Wait\n");
+00000158: E589 LDI R24,0x59 Load immediate
+00000159: E092 LDI R25,0x02 Load immediate
+0000015A: C002 RJMP PC+0x0003 Relative jump
31: printf("Invalid choice\n");
+0000015B: E685 LDI R24,0x65 Load immediate
+0000015C: E092 LDI R25,0x02 Load immediate
+0000015D: 940E02A9 CALL 0x000002A9 Call subroutine
38: }
+0000015F: E080 LDI R24,0x00 Load immediate
+00000160: E090 LDI R25,0x00 Load immediate
+00000161: 900F POP R0 Pop register from stack
+00000162: 91CF POP R28 Pop register from stack
+00000163: 91DF POP R29 Pop register from stack
+00000164: 9508 RET Subroutine return
Thanks guys.
+0000014B: 8189 LDD R24,Y+1 Load indirect with displacement
Here the valueof myinput is copied from memory to register r24. In memory it is located at address Y+1. The value in Y is the address of the byte just before the myinput character.
+0000014C: 3681 CPI R24,0x61 Compare with immediate
+0000014D: F019 BREQ PC+0x04 Branch if equal
Here the value of myinput (in r24) is compared to 0x61='a' (in ascii). If they are equal (myinput=='a') the execution continues at +00000151:
(0x14D+0x4=0x0x151). Else the execution continues with the next instruction.
+0000014E: 3682 CPI R24,0x62 Compare with immediate
+0000014F: F459 BRNE PC+0x0C Branch if not equal
+00000150: C003 RJMP PC+0x0004 Relative jump
Here again the value of myinput (in r24) is compared to 0x62='b' (in ASCII), but now only if they're NOT equal (default case) the execution continues at +0000015B:
(0x14F+0xC=0x0x15B). Else (myinput=='b') the next instruction is a jump to +00000154:
(0x150+0x4=0x0x154).
22: printf("Run program 1\n");
+00000151: E38D LDI R24,0x3D Load immediate
+00000152: E092 LDI R25,0x02 Load immediate
+00000153: C009 RJMP PC+0x000A Relative jump
In the 'a'-casethe argument (actually the memory address of the string) for the printf command is stored in r25:r24. Then the execution branches to the last printf call before the end of the switch statement at +0000015D:
.
26: printf("Run program 2\n");
+00000154: E48B LDI R24,0x4B Load immediate
+00000155: E092 LDI R25,0x02 Load immediate
+00000156: 940E02A9 CALL 0x000002A9 Call subroutine
27: printf("Please Wait\n");
+00000158: E589 LDI R24,0x59 Load immediate
+00000159: E092 LDI R25,0x02 Load immediate
+0000015A: C002 RJMP PC+0x0003 Relative jump
In the 'b'-case, similarly to before, the address of the string to print is stored in r25:r24. Then the execution calls the printf subroutine at memory address0x000002A9
. Then the address of the second string is loaded to r25:r24 and the execution jumps to the last call of printf before the end of the switch statement at +0000015E:
.
Here one can see very well, that the strings are stored in memory, as the first string is 14 (0xE) bytes (chars) long and lies at 0x3D02
; the next string lies at 0x3D02+0xE=0x4D02
!!
31: printf("Invalid choice\n");
+0000015B: E685 LDI R24,0x65 Load immediate
+0000015C: E092 LDI R25,0x02 Load immediate
+0000015D: 940E02A9 CALL 0x000002A9 Call subroutine
In the default case, as before, the string is loaded to r25:r24 and printf is called.
38: }
+0000015F: E080 LDI R24,0x00 Load immediate
+00000160: E090 LDI R25,0x00 Load immediate
+00000161: 900F POP R0 Pop register from stack
+00000162: 91CF POP R28 Pop register from stack
+00000163: 91DF POP R29 Pop register from stack
+00000164: 9508 RET Subroutine return
Cleaning up and return...
I hope this can help you out a bit (even though very late), and if not, may it help someone finding this post on a search while having similar problems!
Offset 0000014C compares "myInput" to 'a' (ASCII 97, hex 0x61) and if equal jumps to offset 00000151 (which is PC+4 at the points of BREQ, offset 0000014D, because the FETCH part of the pipeline is ahead of the EXECUTE part).
If the compare fails, it then compares to 'b' (offset 0000014E), and again branches accordingly.
If that fails, we jump to the last case.
Note there are subtleties in how we call printf (CALL 0x2A9), and where it returns.
User contributions licensed under CC BY-SA 3.0