大理寺少卿 发表于 2025-5-19 23:39:27

X86C++反汇编10.数组

数组改低版本有差异,高版本差异是从2013开始的

### 什么是数组

数组是一组连续且一致的元素的集合

数组的特性:   连续   一致(业务功能)

结构体(成员都是整形)不是数组是因为成员的业务功能不一致

证明一致的方法:

1. 循环,在一个循环中,跑同一块代码的变量业务功能肯定一致
2. 比例因子寻址          reg的取值范围业务类型都一致

因此汇编中证明数组的方法

1. 比例因子寻址          因子寄存器的取值范围可以得到数组的界限
2. 循环结构                   循环次数的取值范围可以得到数组的界限

无法确定范围说明可以通过数组越界读写

## 数组的优化

### 一维数组

##### 比例因子寻址

```
```

**ary的地址=   (int)ary+n \* sizeof(type)**

**因此访问第n个元素 就是   [(int)ary+n \* sizeof(type) ]**

```
int main(int argc, char* argv[])
{
    int ary={1,2,3,4,5};
    ary = 20;         //常量下标访问
    ary = 30;      //变量下标访问
    ary = 50;    //表达式下标访问
}
反汇编代码:
7:      int ary={1,2,3,4,5};
0040D718   mov         dword ptr ,1
0040D71F   mov         dword ptr ,2
0040D726   mov         dword ptr ,3
0040D72D   mov         dword ptr ,4
0040D734   mov         dword ptr ,5
;上面看起来跟反汇编差不多.因此无法构成 是数组的依据
8:      ary = 20;         //常量下标访问
0040D73B   mov         dword ptr ,14h
;这里产生了常量折叠    (ebp - 14h) + 2*4=    ebp - 0Ch;
9:      ary = 30;      //变量下标访问
0040D742   mov         eax,dword ptr
0040D745   mov         dword ptr ,1Eh   
; =>    [(ebp+var_14)+eax*4] ,正常情况 eax 肯定有取值范围,不然就是漏洞
10:       ary = 50;    //表达式下标访问
0040D74D   mov         eax,dword ptr
0040D750   cdq
0040D751   mov         ecx,7
0040D756   idiv      eax,ecx
0040D758   mov         dword ptr ,32h
;先计算表达式,再把结果进行比例因子寻址
11:       return 0;
0040D760   xor         eax,eax


```

##### 无比例因子寻址有指针

在汇编中,判断是否指针 只需要看他是否保存了有效地址,保存了有效地址说明是指针

```
int main(int argc, char* argv[])
{
    int ary={1,2,3,4,5};
    int *p =ary;
    for(int i= 0; i<5 ; i++)
    {
      printf("%d\r\n",*p);
      p++;
    }
    return 0;
}
反汇编代码:
debug版
7:      int ary={1,2,3,4,5};
0040D718   mov         dword ptr ,1
0040D71F   mov         dword ptr ,2
0040D726   mov         dword ptr ,3
0040D72D   mov         dword ptr ,4
0040D734   mov         dword ptr ,5
8:      int *p =ary;
0040D73B   lea      eax,
0040D73E   mov   dword ptr ,eax    ;保存了地址,所以 ebp-18h 这个变量是指针
9:      for(int i= 0; i<5 ; i++)
0040D741   mov         dword ptr ,0   //循环起点
0040D748   jmp         main+53h (0040d753)
0040D74A   mov         ecx,dword ptr
0040D74D   add         ecx,1      //循环步长
0040D750   mov         dword ptr ,ecx
0040D753   cmp         dword ptr ,5   //循环终点
0040D757   jge         main+77h (0040d777)
10:       {
11:         printf("%d\r\n",*p);
0040D759   mov         edx,dword ptr     //从地址 ebp-18h 开始,循环5轮,说明连续且一致
0040D75C   mov         eax,dword ptr       //指针取内容间接访问
0040D75E   push      eax
0040D75F   push      offset string "%d\r\n" (0042201c)
0040D764   call      printf (00401070)
0040D769   add         esp,8
12:         p++;
0040D76C   mov         ecx,dword ptr
0040D76F   add         ecx,4
0040D772   mov         dword ptr ,ecx
13:       }


```

##### 无比例因子无指针

结构体数组不止四个字节,在比例因子寻址时,就会用到imul 获得地址,再寻址

```
int main(int argc, char* argv[])
{
    int ary={1,2,3,4,5};
    for(int i= 0; i<5 ; i++)
    {
      printf("%d\r\n",ary);
   
    }
    return 0;
}
反汇编代码:

DEBUG版

7:      int ary={1,2,3,4,5};
0040D718   mov         dword ptr ,1
0040D71F   mov         dword ptr ,2
0040D726   mov         dword ptr ,3
0040D72D   mov         dword ptr ,4
0040D734   mov         dword ptr ,5
8:      for(int i= 0; i<5 ; i++)
;循环,可以判定数组
0040D73B   mov         dword ptr ,0
0040D742   jmp         main+4Dh (0040d74d)
0040D744   mov         eax,dword ptr
0040D747   add         eax,1
0040D74A   mov         dword ptr ,eax
0040D74D   cmp         dword ptr ,5
0040D751   jge         main+6Ah (0040d76a)
9:      {
10:         printf("%d\r\n",ary);
0040D753   mov         ecx,dword ptr ;从上面可以看出   ebp-18h 的取值范围是 0 - 5
0040D756   mov         edx,dword ptr    ;比例因子寻址可以判定为数组
0040D75A   push      edx
0040D75B   push      offset string "%d\r\n" (0042201c)
0040D760   call      printf (00401070)
0040D765   add         esp,8
11:
12:       }

RELEASE版
release版都变成了指针,没有用到比例因子寻址
.text:00401005               mov   edi, 5
.text:0040100A               mov   , 1
.text:00401012               mov   , 2
.text:0040101A               mov   , 3
.text:00401022               mov   , 4
.text:0040102A               mov   , edi
.text:0040102E               lea   esi,       ;说明这里是数组首地址
.text:00401032
.text:00401032 loc_401032:                         ;循环
.text:00401032               mov   eax,
.text:00401034               push    eax
.text:00401035               push    offset aD       ; "%d\r\n"
.text:0040103A               call    sub_401050
.text:0040103F               add   esp, 8
.text:00401042               add   esi, 4         ;每次加4字节 说明是 dword 数组
.text:00401045               dec   edi   ;循环式比较的是edi--   从5开始递减到0
.text:00401046               jnz   short loc_401032
.text:00401048               pop   edi
.text:00401049               xor   eax, eax
.text:0040104B               pop   esi
.text:0040104C               add   esp, 14h
.text:0040104F               retn
```

!(./notesimg/1658233020355-0b0a882b-2d1a-49f8-b275-649d3b8b4a6c.png)

!(./notesimg/1658233033246-92dfb893-b1c8-4c77-b4d1-7564f88945e5.png)

这样就可以很容看出地址加的偏移

!(./notesimg/1658233063563-9337779b-e53c-42a8-acba-c8de80cf4d93.png)

**高版本 RELEASE 版**

使用了多媒体指令集

.text:00401040               push    ebp

.text:00401041               mov   ebp, esp

.text:00401043               sub   esp, 14h

.text:00401046               movapsxmm0, ds:__xmm@00000004000000030000000200000001

; xmm 是单位,表示128位   xmm0 相当于浮点型寄存中的eax   这里就相当把 1,2,3,4 16字节一次性给xmm0

.text:0040104D               push    esi

.text:0040104E               movupsxmmword ptr , xmm0

;这里相当于 把 xmm0 中 的 1,2,3,4 给数组中的 首地址开始的 16字节

.text:00401052               mov   , 5   ;前面已经给了4个dword ,所以这里直接是5

.text:00401059               xor   esi, esi

.text:0040105B               nop   dword ptr

.text:00401060

.text:00401060 loc_401060:

.text:00401060               push    [**ebp+esi\*4+ary]   ;比例因子, 每个元素长度为4字节**

.text:00401064               push    offset _Format; "%d\r\n"

.text:00401069               call    _printf

.text:0040106E               inc   esi

.text:0040106F               add   esp, 8

.text:00401072               cmp   esi, **5**

.text:00401075               jl      short loc_401060

.text:00401077               xor   eax, eax

.text:00401079               pop   esi

.text:0040107A               mov   esp, ebp

.text:0040107C               pop   ebp

.text:0040107D               retn

###### 多媒体指令集

多媒体指令集:

总共8个寄存器 (xmm0-   xmm7),每个寄存器长度是 128 位 (16字节)除了能做多媒体指令外,还能用于浮点运算和数组的初始化,因此初始化一次就是 4个int,因此很容易把数组初始化完

##### 数组与数组相加

都转成了指针

```
int main(int argc, char* argv[])
{
    int ary={1,2,3,4,5};
    for(int i= 0; i<5 ; i++)
    {
      printf("%d\r\n",ary + ary );
   
    }
    return 0;
}

反汇编代码:
低版本 RELEASE
text:00401000               sub   esp, 14h
.text:00401003               push    ebx
.text:00401004               push    esi
.text:00401005               mov   ebx, 5
.text:0040100A               push    edi
.text:0040100B               mov   , 1
.text:00401013               mov   , 2
.text:0040101B               mov   , 3
.text:00401023               mov   , 4
.text:0040102B               mov   , ebx
.text:0040102F               lea   edi,
.text:00401033               lea   esi,
.text:00401037
.text:00401037 loc_401037:   
                  
.text:00401037               mov   eax,
.text:00401039               mov   ecx,
;eax和   ecx 分别取内容
.text:0040103B               add   eax, ecx
.text:0040103D               push    eax
.text:0040103E               push    offset aD       ; "%d\r\n"
.text:00401043               call    sub_401060
.text:00401048               add   esp, 8

.text:0040104B               sub   esi, 4
.text:0040104E               add   edi, 4
;一个取头,一个取尾
.text:00401051               dec   ebx
.text:00401052               jnz   short loc_401037
.text:00401054               pop   edi
.text:00401055               pop   esi
.text:00401056               xor   eax, eax
.text:00401058               pop   ebx
.text:00401059               add   esp, 14h
.text:0040105C               retn

高版本RELEASE

text:00401040               push    ebp
.text:00401041               mov   ebp, esp
.text:00401043               sub   esp, 14h
.text:00401046               movapsxmm0, ds:__xmm@00000004000000030000000200000001
.text:0040104D               push    esi
.text:0040104E               push    edi
.text:0040104F               movupsxmmword ptr , xmm0
.text:00401053               mov   , 5
.text:0040105A               lea   edi,     ;数组最后一个元素给edi
.text:0040105D               xor   esi, esi
.text:0040105F               nop
.text:00401060
.text:00401060 loc_401060:                     
.text:00401060               mov   eax,    ;数组第一个数给 eax
.text:00401064               add   eax,                            ;2者相加
.text:00401066               push    eax
.text:00401067               push    offset _Format; "%d\r\n"
.text:0040106C               call    _printf
.text:00401071               inc   esi
.text:00401072               lea   edi,
.text:00401075               add   esp, 8
.text:00401078               cmp   esi, 5
.text:0040107B               jl      short loc_401060
.text:0040107D               pop   edi
.text:0040107E               xor   eax, eax
.text:00401080               pop   esi
.text:00401081               mov   esp, ebp
.text:00401083               pop   ebp
.text:00401084               retn
```

#### 字符数组

主要是识别常用的字符串函数,因为 release 版 会直接内联进汇编

```
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
int main(int argc, char* argv[])
{
    char szHello[] = "Hello world!";
    char szBuf;
    strcpy(szBuf, szHello);
    printf(szBuf);
    return strlen(szHello);
}

高版本:
.text:00401050               mov   eax, ds:dword_402108
.text:00401055               movq    xmm0, qword ptr ds:aHelloWo ; "Hello wo"
.text:0040105D               mov   dword ptr , eax
.text:00401060               mov   al, ds:byte_40210C
.text:00401065               mov   , al
.text:00401068               xor   eax, eax
.text:0040106A               movq    qword ptr , xmm0
.text:0040106F               nop
.text:00401070
.text:00401070 loc_401070:                     
.text:00401070               mov   cl,     ;eax取数组首地址
.text:00401074               lea   eax,       
.text:00401077               mov   , cl
.text:0040107B               test    cl, cl                        ;判断 \0
.text:0040107D               jnz   short loc_401070
.text:0040107F               lea   eax,
.text:00401082               push    eax             ; _Format
.text:00401083               call    _printf
.text:00401088               lea   eax,
.text:0040108B               add   esp, 4
.text:0040108E               lea   edx,
.text:00401091
.text:00401091 loc_401091:                     
.text:00401091               mov   cl,
.text:00401093               inc   eax
.text:00401094               test    cl, cl               ;判断 \0
.text:00401096               jnz   short loc_401091
.text:00401098               mov   ecx,
.text:0040109B               sub   eax, edx      ;尾指针 - (头指针 + 1) ,求字符串长度    头+1 是去掉 \0


低版本:
.text:00401000               sub   esp, 24h
.text:00401003               mov   eax, dword_407030
.text:00401008               mov   ecx, dword_407034
.text:0040100E               mov   edx, dword_407038
.text:00401014               mov   , eax
.text:00401018               mov   al, byte_40703C
.text:0040101D               push    esi
.text:0040101E               push    edi
.text:0040101F               mov   , ecx
.text:00401023               mov   , al
.text:00401027               lea   edi,     ;源字符串首地址
.text:0040102B               or      ecx, 0FFFFFFFFh
.text:0040102E               xor   eax, eax
.text:00401030               mov   , edx
.text:00401034               lea   edx,    ;目标字符串首地址
.text:00401038               repne scasb
.text:0040103A               not   ecx
;求长度strlen
.text:0040103C               sub   edi, ecx
.text:0040103E               mov   eax, ecx
.text:00401040               mov   esi, edi
.text:00401042               mov   edi, edx
.text:00401044               shr   ecx, 2       ; /4    四字节拷贝总长度除以四,四字节拷贝次数
.text:00401047               rep movsd      ;四字节拷贝
.text:00401049               mov   ecx, eax
.text:0040104B               and   ecx, 3   ; %4   ,四字节拷贝完,剩下的字节,不足四节一个字节的拷贝
.text:0040104E               rep movsb   ;一字节拷贝
.text:00401050               lea   ecx,
.text:00401054               push    ecx
.text:00401055               call    sub_401080
注意:拷贝前面没有求长度 ,那么 有可能是 memcpy, 有求长度则是 strcpy

.text:0040105A               lea   edi,
.text:0040105E               or      ecx, 0FFFFFFFFh
.text:00401061               xor   eax, eax
.text:00401063               add   esp, 4
.text:00401066               repne scasb   
;repne    不等于就重复al = 0,所以是找 \0    scasb:edi指向的空间是否等于al,如果不等于 ecx-1,edi+1;
.text:00401068               not   ecx
.text:0040106A               dec   ecx          ;如果是strlen(szBuf) + 1 ,则此条指令没有
.text:0040106B               pop   edi
.text:0040106C               mov   eax, ecx
.text:0040106E               pop   esi
.text:0040106F               add   esp, 24h
.text:00401072               retn

分析:      ecx = -1   
=>    -1-Length-1=ecx
=>- Length= ecx +2
=>   Length   = -ecx - 2
=>    Length=neg(ecx ) - 2
=>    Length=not (ecx) + 1- 2
=>    Length=not (ecx) -1
```

!(./notesimg/1658237735543-1f62f8e7-c6d1-427c-b6e9-ec39a65a3c47.png)

对于memcpy如果长度 太小,那么就会直接move 实现, 如果很长 ,在低版本就是 **movsd**和**movsw** ,**scasb** 搭配高版本种可能还有 多媒体指令集

### 二维数组

二维数组在低版本才有优化,高版本无优化(看循环)

二维数组的寻址公式

type ary = {.....}

intx ,y

ary 的地址为:

=(int) ary+ sizeof ( type ) *x            //第一次下标运算得到一维数组ary

```
```

\+ sizeof ( type ) *y                                    //第二次下标运算得到维维数组ary

=    **(int) ary+ sizeof ( type ) \* x   + sizeof ( type ) \*y**          //调试版寻址

= (int) ary+ sizeof ( type) *M * x   + sizeof ( type ) *y

=    **(int) ary+ sizeof ( type ) \*(M\* x+ y)**         //release版寻址

三维数组的寻址公式

type ary = {.....}

intx ,y,z

ary 的地址为:

=(int) ary+ sizeof ( type ) *x            //第一次下标运算得到一维数组ary

```
```

\+ sizeof ( type ) *y                                    //第二次下标运算得到维维数组ary

```
```

\+ sizeof ( type ) *z                                        //第三次下标运算得到维维数组ary

=    **(int)ary +sizeof(type ) \* x + sizeof ( type ) \* y+ sizeof ( type ) \*z**          //调试版寻址

= (int) ary+ sizeof ( type) *M*L * x   + sizeof ( type ) * L *y   + sizeof ( type ) * z

=    **(int) ary+ sizeof ( type ) \*(L \* ( M \* x + y) + z)**         //release版寻址

这时候不管是多维数组还是一维数组,归根结底就是变成了运算符 和 表达式的还原

```
int main(int argc, char* argv[])
{
    int ary ={
      {10,20,30},
      {40,50,60},
    };

    for(int i =0; i<2;i++)
    {
      for(int j =0; j<3;j++)
      {
   
            printf("%d\r\n",ary);
      }
    }
    return 0;
}
反汇编代码:
调试版DEBUG
7:      int ary ={
8:            {10,20,30},
0040D718   mov         dword ptr ,0Ah
0040D71F   mov         dword ptr ,14h
0040D726   mov         dword ptr ,1Eh
9:            {40,50,60},
0040D72D   mov         dword ptr ,28h
0040D734   mov         dword ptr ,32h
0040D73B   mov         dword ptr ,3Ch
10:       };
11:
12:       for(int i =0; i<2;i++)
0040D742   mov         dword ptr ,0
0040D749   jmp         main+54h (0040d754)
0040D74B   mov         eax,dword ptr
0040D74E   add         eax,1
0040D751   mov         dword ptr ,eax
0040D754   cmp         dword ptr ,2
0040D758   jge         main+94h (0040d794)
13:       {
14:         for(int j =0; j<3;j++)
0040D75A   mov         dword ptr ,0
0040D761   jmp         main+6Ch (0040d76c)
0040D763   mov         ecx,dword ptr
0040D766   add         ecx,1
0040D769   mov         dword ptr ,ecx
0040D76C   cmp         dword ptr ,3
0040D770   jge         main+92h (0040d792)
15:         {
16:
17:               printf("%d\r\n",ary);
0040D772   mov         edx,dword ptr
0040D775   imul      edx,edx,0Ch   
0040D778   lea         eax,
;第一次下标运算
0040D77C   mov         ecx,dword ptr
0040D77F   mov         edx,dword ptr     ;比例因子寻址
;第二次下标运算
0040D782   push      edx
0040D783   push      offset string "%d\r\n" (0042201c)
0040D788   call      printf (00401070)
0040D78D   add         esp,8
18:         }
0040D790   jmp         main+63h (0040d763)
19:       }

RELEASE版
int main(int argc, char* argv[])
{
    int ary ={
      {10,20,30},
      {40,50,60},
    };

    int x,y;
    scanf("%d%d",&x,&y);
    ary=999;

    return 0;
}
反汇编代码
.text:00401003               lea   eax,
.text:00401007               lea   ecx,
.text:0040100B               push    eax
.text:0040100C               push    ecx
.text:0040100D               push    offset Format   ; "%d%d"
.text:00401012               call    _scanf
.text:00401017               mov   eax,    ; x
.text:0040101B               mov   edx,     ; y
.text:0040101F               lea   ecx,          ; ecx = 2x + y
.text:00401022               add   eax, ecx                           ;eax =3x+y
.text:00401024               mov   , 3E7h
.text:0040102C               xor   eax, eax
.text:0040102E               add   esp, 2Ch
.text:00401031               retn


int main(int argc, char* argv[])
{
    int ary = {
    {10,20,30},
    {40,50,60},
    };
    int x, y;
    scanf_s("%d%d", &x, &y);
    ary = 999;
    for (int i = 0; i < 2; i++)
    {
      for (int j = 0; j < 3; j++)
      {
            printf("%d\r\n", ary);
      }
    }
    return 0;
}
高版本汇编代码:
.text:004010A0               movapsxmm0, ds:__xmm@000000280000001e000000140000000a
.text:004010A7               lea   eax,
.text:004010AA               push    ebx
.text:004010AB               push    esi
.text:004010AC               push    edi
.text:004010AD               push    eax
.text:004010AE               lea   eax,
.text:004010B1               mov   , 32h
.text:004010B8               push    eax
.text:004010B9               push    offset _Format; "%d%d"
.text:004010BE               movupsxmmword ptr , xmm0
.text:004010C2               mov   , 3Ch
.text:004010C9               call    _scanf_s
.text:004010CE               mov   ecx,
.text:004010D1               lea   esi,
.text:004010D4               mov   eax,
.text:004010D7               add   esp, 0Ch
.text:004010DA               mov   ebx, 2
.text:004010DF               lea   eax,
.text:004010E2               add   eax, ecx
.text:004010E4               mov   , 3E7h    ;比例因子寻址
.text:004010EC               nop   dword ptr
.text:004010F0
.text:004010F0 loc_4010F0:                        
.text:004010F0               mov   edi, 3
.text:004010F5               db      66h, 66h
.text:004010F5               nop   word ptr    ;对齐到0地址
.text:00401100
.text:00401100 loc_401100:                        
.text:00401100               push    dword ptr
.text:00401102               push    offset aD       ; "%d\r\n"
.text:00401107               call    _printf
.text:0040110C               add   esp, 8
.text:0040110F               add   esi, 4
.text:00401112               sub   edi, 1
.text:00401115               jnz   short loc_401100
.text:00401117               sub   ebx, 1
.text:0040111A               jnz   short loc_4010F0
```

编译器经常为了对齐或者其他考虑,或者合并指令的考虑,不一定是从数组首地址寻址 ,而是从数组首地址 +1, -1 的地方开始寻址,这样可以省一条指令,如果不在首地址,寻址的时候,对应的偏移量 页跟着 加或减对应的值就可以了,如果首地址不在第一个元素的位置而在后面元素的地址调整sizeof (type) * n 就可以了

到了数组,会结合前面的很多优化手段,因为存在借指令的情况,即前面的指令,后面直接拿来用

### 借指令

前面的指令,后面直接拿来用,一般是为了节省指令或者减少指令长度

```
int main(int argc, char* argv[])
{
    int ary={1,2,3,4,5};
    for(int i= 0; i<5 ; i++)
    {
      printf("%d\r\n",ary);
    }
    return 0;
}
反汇编代码:
.text:00401005               mov   edi, 5
.text:0040100A               mov   , 1
.text:00401012               mov   , 2
.text:0040101A               mov   , 3
.text:00401022               mov   , 4
.text:0040102A               mov   , edi   ;这本来应该是 5 ,但是为了节省字节用了前面的edi
.text:0040102E               lea   esi,
.text:00401032
.text:00401032 loc_401032:                           ; CODE XREF: _main+46↓j
.text:00401032               mov   eax,
.text:00401034               push    eax
.text:00401035               push    offset aD       ; "%d\r\n"
.text:0040103A               call    sub_401050
.text:0040103F               add   esp, 8
.text:00401042               add   esi, 4
.text:00401045               dec   edi
.text:00401046               jnz   short loc_401032
.text:00401048               pop   edi
.text:00401049               xor   eax, eax
.text:0040104B               pop   esi
.text:0040104C               add   esp, 14h
```

!(./notesimg/1658243113654-d04341ca-b8d3-40cd-8288-931404d69c40.png)

可以看到用寄存器的指令长度要小于 立即数

### 作业

分析 strcmp 的返回结果

```
int main(int argc, char* argv[])
{
    return (int)strcmp(argv,argv);
}

反汇编代码:
.text:00401000               mov   eax,
.text:00401004               push    ebx
.text:00401005               push    esi
.text:00401006               mov   esi,
.text:00401009               mov   eax,
.text:0040100B
.text:0040100B LOOP_BEGIN:                  
.text:0040100B               mov   dl,
.text:0040100D               mov   bl,
.text:0040100F               mov   cl, dl
.text:00401011               cmp   dl, bl
.text:00401013               jnz   short LOOP_END
.text:00401015               test    cl, cl
.text:00401017               jz      short loc_40102F
.text:00401019               mov   dl,
.text:0040101C               mov   bl,
.text:0040101F               mov   cl, dl
.text:00401021               cmp   dl, bl
.text:00401023               jnz   short LOOP_END
.text:00401025               add   eax, 2
.text:00401028               add   esi, 2
.text:0040102B               test    cl, cl
.text:0040102D               jnz   short LOOP_BEGIN
.text:0040102F
.text:0040102F loc_40102F:                     
.text:0040102F               pop   esi
.text:00401030               xor   eax, eax
.text:00401032               pop   ebx
.text:00401033               retn
.text:00401034 ; ---------------------------------------------------------------------------
.text:00401034
.text:00401034 LOOP_END:                        
.text:00401034                                    
.text:00401034               sbb   eax, eax

cmp   dl, bl,当 dl != bl时跳转
当dl >bl   即 str1>str2,cf=0
sbb   =>eax = eax - eax-cf   =>=0
当dl < bl   即 str1< str2, cf = 1
sbb   =>eax = eax - eax-cf   =>= -1

.text:00401036               pop   esi
.text:00401037               sbb   eax, 0FFFFFFFFh

=>eax = eax - ( -1)-cf   
=>eax =0时 cf =0=>   eax = eax - ( -1)-cf   = 1
=>eax =-1时 cf =1   =>   eax = eax - ( -1)-cf   = -1
=>当dl >bl   即 str1> str2    返回值eax =1
=>当dl <bl   即 str1< str2    返回值eax = - 1

.text:0040103A               pop   ebx
.text:0040103B               retn
```

YINXN 发表于 2025-5-20 20:13:52

谢谢分享

AO1199 发表于 2025-5-21 09:32:50

谢谢大佬

hjf571x 发表于 2025-5-26 02:58:41

是个宝藏资料,谢谢了,
页: [1]
查看完整版本: X86C++反汇编10.数组