鱼C论坛

 找回密码
 立即注册
查看: 624|回复: 8

[已解决]汇编代码求解

[复制链接]
发表于 2023-7-13 11:24:34 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 HWitty 于 2023-7-13 11:27 编辑

#include<stdio.h>
int main()
{
        int n = 1;
        scanf("%d",&n);
        switch(n)
        {
                略。
        }
}
**********************************************以下为汇编(程序为debug版无优化)
push ebp
mov ebp,esp
sub esp,8                    ->   源程序中只有一个参数,为啥此处不esp-4,而是esp-8 ?????        
mov dword ptr [ebp-8],1
lea eax,[ebp-8]
push eax
push offset unk_417160
call sub_401130
add esp,8
mov ecx,[ebp-8]                ->   为啥不直接用【ebp-8】地址,而用ecx转到[ebp-4],再cmp。
mov [ebp-4],ecx
cmp dword ptr [ebp-4],1
jz.........

最佳答案
2023-7-13 12:34:39
这段代码是一个简单的 C 语言程序,用于根据用户输入的值 n 执行不同的逻辑。以下是代码的详细解释:

首先,在 main 函数中,一个整型变量 n 被初始化为 1,并使用 scanf 函数从用户输入中读取 n 的新值。

然后,程序进入一个 switch 语句,根据 n 的值执行不同的逻辑。对于每个 case 分支,都有相应的打印语句和 break 语句用于跳出 switch 语句。

现在来分析汇编代码片段:

  1. push ebp                     ; 保存旧的基址指针到栈中
  2. mov ebp, esp                 ; 设置新的基址指针为当前栈顶
  3. sub esp, 8                   ; 在堆栈上分配 8 字节的空间(用于局部变量和临时数据)

  4. mov dword ptr [ebp-8], 1     ; 将值 1 存储到 ebp-8(局部变量 n)中
  5. lea eax, [ebp-8]             ; 计算局部变量 n 的地址,并将其存储到 eax 寄存器中
  6. push eax                     ; 将局部变量 n 的地址推入栈中(作为函数调用的参数)
  7. push offset unk_417160       ; 推入一个位置未知的常量值作为第二个参数
  8. call sub_401130              ; 调用 sub_401130 函数

  9. add esp, 8                   ; 执行函数调用后,根据调用规约恢复栈指针
  10. mov ecx, [ebp-8]             ; 将局部变量 n 的值加载到 ecx 寄存器中
  11. mov [ebp-4], ecx             ; 将 ecx 寄存器中的值存储回 [ebp-4](用于后续的比较操作)

  12. cmp dword ptr [ebp-4], 1     ; 将 [ebp-4](n 的值)与 1 进行比较
  13. jz short loc_401038          ; 如果相等,则跳转到 loc_401038 代码块
  14. cmp dword ptr [ebp-4], 3     ; 将 [ebp-4](n 的值)与 3 进行比较
  15. jz short loc_401047          ; 如果相等,则跳转到 loc_401047 代码块
  16. jmp short loc_401063         ; 否则,跳转到 loc_401063 代码块

  17. loc_401038:                  ; 标签 loc_401038
  18. push offset aN1              ; 推入字符串 "n==1" 的地址作为参数
  19. call sub_4010F0              ; 调用 sub_4010F0 函数(可能是用于打印字符串)
  20. add esp, 4                   ; 根据调用规约恢复栈指针
  21. jmp short loc_401063         ; 跳转到 loc_401063 代码块

  22. loc_401047:                  ; 标签 loc_401047
  23. push offset aN3              ; 推入字符串 "n==3" 的地址作为参数
  24. call sub_4010F0              ; 调用 sub_4010F0 函数(可能是用于打印字符串)
  25. add esp, 4                   ; 根据调用规约恢复栈指针
  26. jmp short loc_401063         ; 跳转到 loc_401063 代码块

  27. loc_401063:                  ; 标签 loc_401063
  28. xor eax, eax                 ; 将 eax 寄存器清零
  29. mov esp, ebp                 ; 恢复栈指针
  30. pop ebp                      ; 恢复旧的基址指针
  31. retn                         ; 返回
复制代码


总之,这个程序的功能是根据用户输入的 n 的值执行相应的逻辑,并打印相应的信息。注意,汇编代码中的函数调用和其他细节可能使用了未给出的代码或数据。

关于你提出的两个问题:

Q:sub esp,8                    ->   源程序中只有一个参数,为啥此处不esp-4,而是esp-8 ?????
A:在这段代码中,sub esp, 8 操作是为了在堆栈上分配足够的空间来存储局部变量和临时数据。在大多数情况下,函数调用使用堆栈来传递参数和保存返回地址,所以在函数开始时先给堆栈分配一些额外的空间。
Q:mov ecx,[ebp-8]                ->   为啥不直接用【ebp-8】地址,而用ecx转到[ebp-4],再cmp。
A:关于第二个问题,这段代码是将 [ebp-8] 中的值加载到 ecx 寄存器中,并将其存储到 [ebp-4],而不直接使用 [ebp-8] 的原因可能是为了后续比较操作的方便。通过将值从 [ebp-8] 复制到 [ebp-4],可以方便地与其他值进行比较,而不需要再次访问 [ebp-8]。这样的操作可能是为了简化代码或者遵循特定的编码风格。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-7-13 11:30:03 | 显示全部楼层
本帖最后由 歌者文明清理员 于 2023-7-13 11:31 编辑

在你提供的代码片段中,有一些疑问和注意事项:

  • 关于 sub esp,8:在函数开头,通常会为局部变量分配一些空间。在这个代码片段中,sub esp, 8 分配了 8 字节的空间。这可能是因为编译器需要一些额外的空间来执行其他操作,或者是为栈帧保留的空间。
  • 关于 mov ecx, [ebp-8] 和 mov [ebp-4], ecx:这两个操作是将局部变量 n(位于 [ebp-8])的值复制到 ecx 寄存器中,并将 ecx 中的值复制回 [ebp-4]。这可能是为了方便在后续的操作中使用 ecx 寄存器。
  • 缺少 case 分支:你提供的代码片段中省略了 switch 语句的具体 case 分支。如果你需要更详细的帮助,请提供完整的代码,我将尽力为你解答。


总体而言,我建议对代码进行进一步分析和调试,以便更好地理解程序的逻辑和目的。

详细版:

当进入 main 函数时,以下是代码片段中的汇编指令的详细解释:

  1. push ebp         ; 保存旧的基址指针到栈中
  2. mov ebp, esp     ; 设置新的基址指针为当前栈顶
  3. sub esp, 8       ; 在堆栈上分配 8 字节的空间(用于局部变量和临时数据)

  4. mov dword ptr [ebp-8], 1  ; 将值 1 存储到 ebp-8(局部变量 n)中
  5. lea eax, [ebp-8]          ; 计算局部变量 n 的地址,并将其存储到 eax 寄存器中
  6. push eax                  ; 将局部变量 n 的地址推入栈中(作为函数调用的参数)
  7. push offset unk_417160    ; 推入一个位置未知的常量值作为第二个参数
  8. call sub_401130           ; 调用 sub_401130 函数

  9. add esp, 8                ; 执行函数调用后,根据调用规约恢复栈指针
  10. mov ecx, [ebp-8]          ; 将局部变量 n 的值加载到 ecx 寄存器中
  11. mov [ebp-4], ecx          ; 将 ecx 寄存器中的值存储回 [ebp-4](用于后续的比较操作)

  12. cmp dword ptr [ebp-4], 1  ; 将 [ebp-4](n 的值)与 1 进行比较
  13. jz ...                    ; 如果相等,则跳转到指定的代码块

  14. ; 省略其他 case 分支和代码块
复制代码

这个汇编代码片段首先设置了函数的栈帧,然后将值 1 存储到局部变量 n 中。然后,它调用了一个函数,并使用 lea 指令计算并推入局部变量 n 的地址作为函数调用的参数。

接下来,它将局部变量 n 的值加载到 ecx 寄存器中,并将其存储回另一个局部变量(位于 [ebp-4])。然后,它使用 cmp 指令将这个值与 1 进行比较,根据比较的结果进行条件跳转。

请注意,由于你提供的代码片段省略了部分细节,无法完全了解它的功能和逻辑。如果你需要更详细的解释,请提供完整的代码,我将尽力为你提供帮助。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-7-13 12:19:38 | 显示全部楼层
歌者文明清理员 发表于 2023-7-13 11:30
在你提供的代码片段中,有一些疑问和注意事项:

完整代码

1

1

2

2
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-7-13 12:20:26 | 显示全部楼层
网站只支持2m图片上传,太难受了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-7-13 12:24:25 | 显示全部楼层
HWitty 发表于 2023-7-13 12:20
网站只支持2m图片上传,太难受了

wodetu.cn
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-7-13 12:32:02 | 显示全部楼层
  1. #include<stdio.h>
  2. int main()
  3. {
  4.         int n = 1;
  5.         scanf("%d",&n);
  6.         switch(n)
  7.         {
  8.                 case 1:
  9.                         printf("n==1");
  10.                         break;
  11.                 case 3:
  12.                         printf("n==3");
  13.                         brealk;
  14.                 case 100:
  15.                         printf("n=100");
  16.                         break;
  17.         }
  18. }
复制代码

  1. push        ebp
  2. mov        ebp, esp
  3. sub        esp, 8
  4. mov        dword ptr [ebp-8], 1
  5. lea        eax, [ebp-8]
  6. push        eax
  7. push        offset unk_417160
  8. call        sub_401130
  9. add        esp, 8
  10. mov        ecx, [ebp-8]
  11. mov        [ebp-4], ecx
  12. cmp        dword ptr [ebp-4], 1
  13. jz        short loc_401038
  14. cmp        dword ptr [ebp-4], 3
  15. jz        short loc_401047
  16. jmp        short loc_401063
  17. {
  18. push         offset aN1
  19. call         sub_4010F0
  20. add        esp, 4
  21. }
  22. jmp         short loc_401063
  23. {
  24. push         offset aN1
  25. call         sub_4010F0
  26. add        esp, 4
  27. }
  28. jmp         short loc_401063
  29. {
  30. push         offset aN1
  31. call         sub_4010F0
  32. add        esp, 4
  33. }
  34. xor        eax, eax
  35. mov        esp, ebp
  36. pop        ebp
  37. retn
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-7-13 12:34:39 | 显示全部楼层    本楼为最佳答案   
这段代码是一个简单的 C 语言程序,用于根据用户输入的值 n 执行不同的逻辑。以下是代码的详细解释:

首先,在 main 函数中,一个整型变量 n 被初始化为 1,并使用 scanf 函数从用户输入中读取 n 的新值。

然后,程序进入一个 switch 语句,根据 n 的值执行不同的逻辑。对于每个 case 分支,都有相应的打印语句和 break 语句用于跳出 switch 语句。

现在来分析汇编代码片段:

  1. push ebp                     ; 保存旧的基址指针到栈中
  2. mov ebp, esp                 ; 设置新的基址指针为当前栈顶
  3. sub esp, 8                   ; 在堆栈上分配 8 字节的空间(用于局部变量和临时数据)

  4. mov dword ptr [ebp-8], 1     ; 将值 1 存储到 ebp-8(局部变量 n)中
  5. lea eax, [ebp-8]             ; 计算局部变量 n 的地址,并将其存储到 eax 寄存器中
  6. push eax                     ; 将局部变量 n 的地址推入栈中(作为函数调用的参数)
  7. push offset unk_417160       ; 推入一个位置未知的常量值作为第二个参数
  8. call sub_401130              ; 调用 sub_401130 函数

  9. add esp, 8                   ; 执行函数调用后,根据调用规约恢复栈指针
  10. mov ecx, [ebp-8]             ; 将局部变量 n 的值加载到 ecx 寄存器中
  11. mov [ebp-4], ecx             ; 将 ecx 寄存器中的值存储回 [ebp-4](用于后续的比较操作)

  12. cmp dword ptr [ebp-4], 1     ; 将 [ebp-4](n 的值)与 1 进行比较
  13. jz short loc_401038          ; 如果相等,则跳转到 loc_401038 代码块
  14. cmp dword ptr [ebp-4], 3     ; 将 [ebp-4](n 的值)与 3 进行比较
  15. jz short loc_401047          ; 如果相等,则跳转到 loc_401047 代码块
  16. jmp short loc_401063         ; 否则,跳转到 loc_401063 代码块

  17. loc_401038:                  ; 标签 loc_401038
  18. push offset aN1              ; 推入字符串 "n==1" 的地址作为参数
  19. call sub_4010F0              ; 调用 sub_4010F0 函数(可能是用于打印字符串)
  20. add esp, 4                   ; 根据调用规约恢复栈指针
  21. jmp short loc_401063         ; 跳转到 loc_401063 代码块

  22. loc_401047:                  ; 标签 loc_401047
  23. push offset aN3              ; 推入字符串 "n==3" 的地址作为参数
  24. call sub_4010F0              ; 调用 sub_4010F0 函数(可能是用于打印字符串)
  25. add esp, 4                   ; 根据调用规约恢复栈指针
  26. jmp short loc_401063         ; 跳转到 loc_401063 代码块

  27. loc_401063:                  ; 标签 loc_401063
  28. xor eax, eax                 ; 将 eax 寄存器清零
  29. mov esp, ebp                 ; 恢复栈指针
  30. pop ebp                      ; 恢复旧的基址指针
  31. retn                         ; 返回
复制代码


总之,这个程序的功能是根据用户输入的 n 的值执行相应的逻辑,并打印相应的信息。注意,汇编代码中的函数调用和其他细节可能使用了未给出的代码或数据。

关于你提出的两个问题:

Q:sub esp,8                    ->   源程序中只有一个参数,为啥此处不esp-4,而是esp-8 ?????
A:在这段代码中,sub esp, 8 操作是为了在堆栈上分配足够的空间来存储局部变量和临时数据。在大多数情况下,函数调用使用堆栈来传递参数和保存返回地址,所以在函数开始时先给堆栈分配一些额外的空间。
Q:mov ecx,[ebp-8]                ->   为啥不直接用【ebp-8】地址,而用ecx转到[ebp-4],再cmp。
A:关于第二个问题,这段代码是将 [ebp-8] 中的值加载到 ecx 寄存器中,并将其存储到 [ebp-4],而不直接使用 [ebp-8] 的原因可能是为了后续比较操作的方便。通过将值从 [ebp-8] 复制到 [ebp-4],可以方便地与其他值进行比较,而不需要再次访问 [ebp-8]。这样的操作可能是为了简化代码或者遵循特定的编码风格。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-7-13 13:16:35 | 显示全部楼层

大哥,什么意思 没懂
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-7-13 13:18:49 | 显示全部楼层
HWitty 发表于 2023-7-13 13:16
大哥,什么意思 没懂

图床
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-4-27 22:34

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表