嘿所以这里只是我在c中编写的一个简单程序,在avr-gcc下编译。 相应的汇编代码也已过帐。
仍然无法理解switch语句的汇编代码在做什么,任何帮助都会很棒。感谢。
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;
返回0;
}
汇编代码:
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
谢谢你们。
答案 0 :(得分:1)
+0000014B: 8189 LDD R24,Y+1 Load indirect with displacement
此处myinput的值从内存复制到寄存器r24。在内存中,它位于地址Y + 1。 Y中的值是myinput字符之前的字节地址。
+0000014C: 3681 CPI R24,0x61 Compare with immediate
+0000014D: F019 BREQ PC+0x04 Branch if equal
这里将myinput的值(在r24中)与0x61 =' a'进行比较。 (在ascii中)。如果它们相等(myinput ==' a'),执行将继续+00000151:
(0x14D + 0x4 = 0x0x151)。否则继续执行下一条指令。
+0000014E: 3682 CPI R24,0x62 Compare with immediate
+0000014F: F459 BRNE PC+0x0C Branch if not equal
+00000150: C003 RJMP PC+0x0004 Relative jump
再次将myinput(在r24中)的值与0x62 =' b'进行比较。 (在ASCII中),但现在只有当它们 NOT 相等(默认情况)时,执行才会继续+0000015B:
(0x14F + 0xC = 0x0x15B)。否则(myinput ==' b')下一条指令是跳转到+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
在' -case中,printf命令的参数(实际上是字符串的内存地址)存储在r25:r24中。然后执行在+0000015D:
的switch语句结束之前分支到最后一次printf调用。
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
在'' -case中,与之前类似,要打印的字符串的地址存储在r25:r24中。然后执行调用内存地址0x000002A9
的printf子例程。然后第二个字符串的地址加载到r25:r24,并且执行跳转到在+0000015E:
的switch语句结束之前最后一次调用printf。
这里可以很好地看到,字符串存储在内存中,因为第一个字符串是14(0xE)字节(字符串)长并位于0x3D02
;下一个字符串位于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
在默认情况下,和以前一样,字符串被加载到r25:r24并调用printf。
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
清理并返回...
我希望这可以帮助你一点点(即使很晚),如果没有,可能会帮助有人在搜索时找到这个帖子同时遇到类似的问题!
答案 1 :(得分:0)
偏移0000014C将“myInput”与“a”(ASCII 97,十六进制0x61)进行比较,如果相等则跳转到偏移量00000151(在BREQ点为PC + 4,偏移量为0000014D,因为管道的FETCH部分为在EXECUTE部分之前)。
如果比较失败,则比较为'b'(偏移0000014E),并再次进行分支。
如果失败,我们跳到最后一个案例。
请注意,我们如何调用printf(CALL 0x2A9)以及它返回的位置存在细微之处。