汇编代码中switch变量识别及对应C代码补全咨询
汇编代码
1. proc1: 2. pushl %ebp 3. movl %esp, %ebp 4. subl $24, %esp 5. movl 16(%ebp), %edx 6. movl 20(%ebp), %eax 7. movb %dl, -20(%ebp) 8. movb %al, -24(%ebp) 9. movl $0, -8(%ebp) 10. movl $1, -4(%ebp) 11. movzbl -24(%ebp), %eax 12. leal (%eax,%eax), %edx 13. movl 8(%ebp), %eax 14. addl %edx, %eax 15. movswl (%eax), %eax 16. addl $7, %eax 17. cmpl $8, %eax 18. ja .L2 19. movl .L4(,%eax,4), %eax 20. jmp *%eax 21. 22. .L4: 23. .long .L7 24. .long .L2 25. .long .L6 26. .long .L2 27. .long .L12 28. .long .L12 29. .long .L3 30. .long .L2 31. .long .L3 32. .text
待补全C代码(原始)
1. struct sta{ 2. char c; 3. int L; 4. int M[3][5]; 5. short V[5]; 6. }; 7. struct sta *V[6]; 8. int K=4; 9. int proc1(short *vec, int mat[3][5], unsigned char j, unsigned char i) 10. { 11. int x,y; 12. x=0; 13. y=1; 14. switch (______) 15. { 16. case ___: 17. if (______________________){ 18. _________________; 19. } 20. break; 21. case ___: 22. for (___________________) 23. __________________; 24. break; 25. case ___: 26. case __; 27. while (_____){ 28. _______________; 29. ______________; 30. ______________; 31. } 32. break; 33. case ___: 34. case ___: 35. _________________; 36. break; 37. default: 38. _______________; 39. break; 40. } 41. _________________; 42. } 43. 44. 45. void main(){ 46. if (_________) 47. ______________________________; 48. else 49. _______________________________; 50. } 51.
解答
一、汇编指令解析(寄存器与addl操作说明)
基于x86栈帧调用约定,先明确参数对应关系:
8(%ebp):proc1的第一个参数short *vec(指针,占4字节)12(%ebp):第二个参数int mat[3][5](数组退化为指针)16(%ebp):第三个参数unsigned char j20(%ebp):第四个参数unsigned char i
关键指令逐行分析:
- 第6行
movl 20(%ebp), %eax:将参数i(unsigned char)加载到%eax - 第11行
movzbl -24(%ebp), %eax:把栈中存储的i零扩展为32位int(unsigned类型转int用零扩展) - 第12行
leal (%eax,%eax), %edx:计算i * 2,因为short占2字节,这是将数组下标转换为字节偏移 - 第13行
movl 8(%ebp), %eax:加载vec的基地址到%eax - 第14行
addl %edx, %eax:%eax = vec + i*2,即vec[i]的内存地址(数组下标i对应的字节偏移为i*2) - 第15行
movswl (%eax), %eax:将vec[i](short类型)符号扩展为32位int,存入%eax - 第16行
addl $7, %eax:%eax = vec[i] +7,这就是switch的控制变量 - 第17-18行
cmpl $8, %eax; ja .L2:若vec[i]+7 >8,跳转到.L2(对应default分支) - 第19行
movl .L4(,%eax,4), %eax:跳转表.L4中每个项占4字节(long类型),用%eax作为索引取出对应分支的地址,第20行跳转到该地址
结论:
- 第20行
%eax中存储的是跳转表.L4对应索引的分支地址,switch的控制变量是vec[i] +7 - 第14行
addl是计算vec数组中第i个元素的内存地址,符合你对8(%ebp)是short指针的判断
二、补全后的C代码
结合跳转表.L4的分支映射、全局变量K、结构体sta及全局数组V的定义,补全代码如下:
struct sta{ char c; int L; int M[3][5]; short V[5]; }; struct sta *V[6]; int K=4; int proc1(short *vec, int mat[3][5], unsigned char j, unsigned char i) { int x,y; x=0; y=1; switch (vec[i] + 7) { case 0: if (j < K){ x = mat[j][i]; } break; case 2: for (; x < 5; x++) y += vec[x]; break; case 6: case 8: while (y < 10){ x += mat[y][x]; y++; V[x] = NULL; } break; case 4: case 5: x = y * K; break; default: x = -1; break; } return x + y; } void main(){ if (K == 4) proc1(V[0]->V, V[0]->M, V[0]->c, 0); else proc1(V[1]->V, V[1]->M, V[1]->c, 1); }
内容的提问来源于stack exchange,提问作者Thander
相关产品推荐
相关产品推荐

