吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 3627|回复: 21
收起左侧

[调试逆向] 【原创】另类汇编解反转数字题

[复制链接]
lyl610abc 发表于 2021-3-5 20:37
本帖最后由 lyl610abc 于 2021-3-6 12:01 编辑

先前学习了不少汇编的内容,来整点新花样,试试用汇编来解决一些简单的题目

题目

给定一个32位的有符号数x,返回x中每位上的数字反转后的结果。

假设环境不允许存储64位整数(有符号或无符号)

示例1:

输入:x = 123
输出:321

示例2:

输入:x = -123
输出:-321

示例3:

输入:x = 120
输出:21

解题代码

#include "stdafx.h"

void revert(int num){
        int sign=0;
        int cnt=0;
        int arr[50]={0};
        if(num<0){
                num=-num;
                sign=1;
        }
        __asm{                
                 mov         eax,num                 
_begin:
                 cdq
                 mov         ecx,0Ah
                 div        ecx                
                 mov ebx,cnt
                 lea ecx,dword ptr[arr+ebx*4]
                 inc cnt
                 mov dword ptr [ecx],edx
                 test eax,eax
                 jnz   _begin
_ret:

        }        
        if(sign){
                printf("-");
        }

        int i=0;
        while(arr[i]==0){
                i++;
        }
        for(;i<cnt;i++){

                printf("%d",arr[i]);
        }
        printf("\n");

}
int main(int argc, char* argv[])
{
        revert(-10086);
        return 0;
}

运行结果

image-20210305195640877

整体代码分析

整体代码就是做了以下几个工作:

  1. 判断参数是否为负数,如果是负数,则取其绝对值,并在后面输出时会先输出一个符号
  2. 通过汇编依次将除以10的余数存入数组中,并记录下位数
  3. 将数组头部为0的部分跳过,不输出
  4. 输出数组的剩下有效部分

汇编代码分析

__asm{                
                 mov         eax,num                 
_begin:
                 cdq
                 mov         ecx,0Ah
                 div        ecx                
                 mov ebx,cnt
                 lea ecx,dword ptr[arr+ebx*4]
                 inc cnt
                 mov dword ptr [ecx],edx
                 test eax,eax
                 jnz   _begin
_ret:

        }        

可以看到汇编的代码非常简洁,只有短短几行

来分析一下这段代码做了些什么:

首先将要被反转的数赋值给eax

 mov         eax,num        

_begin

接着声明一个程序段_beign,用于之后跳回来实现循环

_begin:

cdq指令

接着是一个新的汇编代码:

cdq

cdq—Convert Double to Quad (386+),该指令把edx扩展为eax的高位,也就是借助两个寄存器来存储一个64位的数

以123为例,看一下cdq执行前和执行后的效果:

执行前

image-20210305201746298

此时EAX为7B,也就是123的十六进制,EDX则暂不清楚数据含义

执行后

image-20210305201839397

执行后,可以发现EDX被清零了,效果和movsx类似,只不过被扩展的高位存放在edx中

为什么要进行扩展?之后的div指令所要求的,且先向下看


然后是将除数10赋值给ecx,10的十六进制对应A

mov         ecx,0Ah

div指令

再接着就是div指令了

先介绍一下div指令


div为无符号除法  ; idiv为有符号除法

div 指令只需要一个操作数,即除数

既然div指令只给出的除数,那么被除数呢?

被除数:

  • 如果除数为8位, 被除数则为 16 位, 在 ax 中存放
  • 如果除数为16位, 被除数则为 32 位, 在 dx 和 ax 中存放, dx 存放高 16 位, ax 存放低 16 位
  • 如果除数为32位,被除数则为64为,在edx和eax中存放,edx存放高16位,eax存放低16位

接着看我们的代码:

div        ecx

我们指定ecx为除数,除数ecx=10


依旧以123为例,查看div指令执行前后寄存器的变化

执行前

image-20210305202057096

执行前EDX和EAX组成除数,0x00000000 0000007B = 123;ECX作为除数0x0A=10

执行后

image-20210305202212223

执行后可以看到EAX=0x0C=12,EDX=3

得知,div指令执行后EAX存放除后的结果,EDX存放除后的余数


数据放入数组

得到除后的结果和余数以后,就将余数存放到数组即可

                 mov ebx,cnt
                 lea ecx,dword ptr[arr+ebx*4]
                 inc cnt
                 mov dword ptr [ecx],edx
  1. 这里先将cnt(用来记录被除数的位数)赋值给ebx
  2. 然后通过lea指令获得要存放的数组的成员位置
  3. 获取完成后,将cnt加1
  4. 然后就是将edx也就是余数存放到数组中

有关数组的知识可回顾: 逆向基础笔记十六 汇编一维数组


比较循环

                 test eax,eax
                 jnz   _begin

判断eax是否为0,如果不为0,则继续跳到先前的代码继续执行循环,直到被除数为0才跳出循环


_ret

这后面并没有写代码,只是声明了一个返回的段,算是为了代码的结构完整性吧


总结

将数字顺序反转这种入门题算是十分经典了,但用汇编来完成的人却并不多,通过这个案例来巩固之前所学的汇编知识,加强理解。

PS:不同于以往对汇编冗余的观念,在某些场景使用汇编反而会更简洁,而非更加冗余,这个案例就展现出汇编的优点;但并非所有项目都适合使用汇编,不要为了用汇编而用汇编,要结合具体场景考虑

免费评分

参与人数 7威望 +1 吾爱币 +26 热心值 +7 收起 理由
Hmily + 1 + 20 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
冰棍好烫啊 + 1 + 1 很详细
shiina0831 + 1 + 1 谢谢@Thanks!
朱朱你堕落了 + 1 + 1 大佬基础知识真扎实!
Jamsenyc + 1 + 1 我很赞同!
Mr.G74 + 1 + 1 我很赞同!
zjun777 + 1 + 1 用心讨论,共获提升!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

losingstars 发表于 2021-3-5 21:25
学习了。谢谢楼主。
国际豆哥 发表于 2021-3-5 21:26
学习来学习了,一看见这个大佬的帖子我啪的一下我就点进来了啊,很快啊!
YMYS 发表于 2021-3-5 21:27
阿姨洗铁路86 发表于 2021-3-5 22:29
厉害了大佬
whngomj 发表于 2021-3-5 22:46

学习了。谢谢楼主。
376408384 发表于 2021-3-6 09:59
数组只有10位 不怕越界吗?

免费评分

参与人数 1吾爱币 +1 热心值 +1 收起 理由
lyl610abc + 1 + 1 感谢您的宝贵建议,我们会努力争取做得更好!

查看全部评分

lfm107 发表于 2021-3-6 10:07
学习了,谢谢分享
ifenglmy 发表于 2021-3-6 10:33
谢谢楼主分享。。
 楼主| lyl610abc 发表于 2021-3-6 11:59
376408384 发表于 2021-3-6 09:59
数组只有10位 不怕越界吗?

当初随便写了个10,没去注意
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-12-4 16:38

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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