HWitty 发表于 2023-7-13 11:24:34

汇编代码求解

本帖最后由 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 ,1
lea eax,
push eax
push offset unk_417160
call sub_401130
add esp,8
mov ecx,                ->   为啥不直接用【ebp-8】地址,而用ecx转到,再cmp。
mov ,ecx
cmp dword ptr ,1
jz.........

歌者文明清理员 发表于 2023-7-13 11:30:03

本帖最后由 歌者文明清理员 于 2023-7-13 11:31 编辑

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


[*]关于 sub esp,8:在函数开头,通常会为局部变量分配一些空间。在这个代码片段中,sub esp, 8 分配了 8 字节的空间。这可能是因为编译器需要一些额外的空间来执行其他操作,或者是为栈帧保留的空间。

[*]关于 mov ecx, 和 mov , ecx:这两个操作是将局部变量 n(位于 )的值复制到 ecx 寄存器中,并将 ecx 中的值复制回 。这可能是为了方便在后续的操作中使用 ecx 寄存器。

[*]缺少 case 分支:你提供的代码片段中省略了 switch 语句的具体 case 分支。如果你需要更详细的帮助,请提供完整的代码,我将尽力为你解答。


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

详细版:

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

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

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

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

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

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

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

请注意,由于你提供的代码片段省略了部分细节,无法完全了解它的功能和逻辑。如果你需要更详细的解释,请提供完整的代码,我将尽力为你提供帮助。

HWitty 发表于 2023-7-13 12:19:38

歌者文明清理员 发表于 2023-7-13 11:30
在你提供的代码片段中,有一些疑问和注意事项:




完整代码

HWitty 发表于 2023-7-13 12:20:26

网站只支持2m图片上传,太难受了

歌者文明清理员 发表于 2023-7-13 12:24:25

HWitty 发表于 2023-7-13 12:20
网站只支持2m图片上传,太难受了

wodetu.cn

歌者文明清理员 发表于 2023-7-13 12:32:02

#include<stdio.h>
int main()
{
        int n = 1;
        scanf("%d",&n);
        switch(n)
        {
                case 1:
                        printf("n==1");
                        break;
                case 3:
                        printf("n==3");
                        brealk;
                case 100:
                        printf("n=100");
                        break;
        }
}

push        ebp
mov        ebp, esp
sub        esp, 8
mov        dword ptr , 1
lea        eax,
push        eax
push        offset unk_417160
call        sub_401130
add        esp, 8
mov        ecx,
mov        , ecx
cmp        dword ptr , 1
jz        short loc_401038
cmp        dword ptr , 3
jz        short loc_401047
jmp        short loc_401063
{
push         offset aN1
call         sub_4010F0
add        esp, 4
}
jmp         short loc_401063
{
push         offset aN1
call         sub_4010F0
add        esp, 4
}
jmp         short loc_401063
{
push         offset aN1
call         sub_4010F0
add        esp, 4
}
xor        eax, eax
mov        esp, ebp
pop        ebp
retn

歌者文明清理员 发表于 2023-7-13 12:34:39

这段代码是一个简单的 C 语言程序,用于根据用户输入的值 n 执行不同的逻辑。以下是代码的详细解释:

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

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

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

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

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

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

cmp dword ptr , 1   ; 将 (n 的值)与 1 进行比较
jz short loc_401038          ; 如果相等,则跳转到 loc_401038 代码块
cmp dword ptr , 3   ; 将 (n 的值)与 3 进行比较
jz short loc_401047          ; 如果相等,则跳转到 loc_401047 代码块
jmp short loc_401063         ; 否则,跳转到 loc_401063 代码块

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

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

loc_401063:                  ; 标签 loc_401063
xor eax, eax               ; 将 eax 寄存器清零
mov esp, ebp               ; 恢复栈指针
pop ebp                      ; 恢复旧的基址指针
retn                         ; 返回

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

关于你提出的两个问题:

Q:sub esp,8                  ->   源程序中只有一个参数,为啥此处不esp-4,而是esp-8 ?????
A:在这段代码中,sub esp, 8 操作是为了在堆栈上分配足够的空间来存储局部变量和临时数据。在大多数情况下,函数调用使用堆栈来传递参数和保存返回地址,所以在函数开始时先给堆栈分配一些额外的空间。

Q:mov ecx,                ->   为啥不直接用【ebp-8】地址,而用ecx转到,再cmp。
A:关于第二个问题,这段代码是将 中的值加载到 ecx 寄存器中,并将其存储到 ,而不直接使用 的原因可能是为了后续比较操作的方便。通过将值从 复制到 ,可以方便地与其他值进行比较,而不需要再次访问 。这样的操作可能是为了简化代码或者遵循特定的编码风格。

HWitty 发表于 2023-7-13 13:16:35

歌者文明清理员 发表于 2023-7-13 12:24
wodetu.cn

大哥,什么意思 没懂

歌者文明清理员 发表于 2023-7-13 13:18:49

HWitty 发表于 2023-7-13 13:16
大哥,什么意思 没懂

图床
页: [1]
查看完整版本: 汇编代码求解