用于添加两个3位数comp3类型的逻辑

时间:2017-02-14 07:14:40

标签: x86 cobol disassembly

我得到了x86代码,用于添加两个具有comp3类型的数字(参见cobol),添加逻辑非常奇怪且令人困惑但是给出了正确的结果。可以帮助我使用此代码

>>00401229<<  add         eax,33333333h    ;  [00 00 01 23] + [33 33 33 33] = [33 33 34 56]eax  

0040122E  add         edx,33333333h        ;  [00 00 02 20] + [33 33 33 33] = [33 33 35 53]edx

00401234  mov         ebx,eax          ; copying eax to ebx   ; ebx = eax = 33 33 34 56

00401236  xor         ebx,edx          ; [33 33 34 56] xor [33 33 35 53] = [00 00 01 05](EBX)

00401238  add         eax,edx          ; [33 33 34 56]eax  + [33 33 35 53]edx = [66 66 69 A9]eax 

0040123A  xor         ebx,eax          ; [00 00 01 05](ebx) xor [66 66 69 A9](eax) = [66 66 68 AC](ebx)

0040123C  shr         ebx,3                ; 3 >> [66 66 68 AC](ebx) =  [0C CC CD 15](ebx)

0040123F  not         ebx                  ; [0C CC CD 15](ebx) NOT  ==>  [F3 33 32 EA](ebx)

00401241  and         ebx,22222222h        ; [F3 33 32 EA](ebx) & [22 22 22 22] = [22 22 22 22]

00401247  lea         ebx,[ebx+ebx*2]      ;ebx = 66 66 66 66

0040124A  sub         eax,ebx          ;[66 66 69 A9]eax - [66 66 66 66]ebx = 343 

更多代码可能不相关

004011D1  mov         eax,3C120000h                     // EAX = 3C120000h 

004011D6  mov         dword ptr [$HELLO.DATA+0D8h (409A08h)],eax   // at  409A08h moving data 00 00 12 3c

004011DB  mov         eax,0C220000h                    // EAX = 0C220000h   

004011E0  mov         dword ptr [$HELLO.DATA+0E0h (409A10h)],eax   // at 409A10h moving data 00 00 22 0c

004011E5  sub         eax,eax                      // may be clearing eax

004011E7  mov         eax,dword ptr [$HELLO.DATA+0D8h (409A08h)]   // copying from  409A08h data(00 00 12 3c) to EAX

004011EC  bswap       eax                      // eax becomes  00 00 12 3c from 3C 12 00 00h

004011EE  sub         edx,edx                      //  perhaps clearing edx

004011F0  mov         edx,dword ptr [$HELLO.DATA+0E0h (409A10h)]  // copying from  409A08h data 00 00 22 0c to EDX

004011F6  bswap       edx                     //   edx becomes  00 00 22 0c from  0C 22 00 00

004011F8  mov         ebx,eax ....................................// copying from eax to ebx , ebx becomes 00 00 12 3c  


004011FA  and         ebx,0Fh ....................................// ebx & 0Fh,(00 00 12 3c)&(0Fh) => 00 00 00 0C
                                  // extracting sign from value ebx ,storing 'C' in ebx

004011FD  mov         ch,byte ptr $HELLO.LIT+230h (40E230h)[ebx]  // 'ch' refer to 8 to 15 bits of ecx register         
                                  // ecx register -> |_15 to 8_| 7 to 0|  , 
                                  // byte from ebx  is copied to ecx position 8 to 15 

00401203  mov         ebx,edx                     // value of edx ( 00 00 22 0C ) copied to ebx  

00401205  and         ebx,0Fh                     // extracting sign of second no by preserving last        

                             nibble , now ebx has sign of second no i.e 'C'

00401208  mov         cl,byte ptr $HELLO.LIT+230h (40E230h)[ebx]  //   'CL' refer to '0 TO 7th' bit of 'E C X'
                                  // Copying last 7 bits of ebx to cl 
                                  // ECX Becomes ECX =  8E 19 '0C' '0C' 
                                  // contains sign of both var ,     var1 and var 2
                                                  15 to 8 and 7 to 0

0040120E  shr         eax,4                   // shifitng EAX right , removing sign nibble from var1

00401211  shr         edx,4                       // shifitng EDX right , removing sign nibble from var2

                                var2 , EDX = 00000220
                                var1 , EAX = 00000123 


00401214  cmp         ch,cl                     // comparing the sign of both number 
                                // Both ch & cl part of ECX

                //CMP - If the two values are equal, the Z Flag is set (1) otherwise it is not set (0)



00401216  je          $HELLO.CODE+219h (401229h)  // if both sign equal jump to '401229h'

                //JE and JZ : a conditional jump when ZF (the "zero" flag) is equal to 1.

                            //  var2 , EDX = 00000220
                            //  var1 , EAX = 00000123 

1 个答案:

答案 0 :(得分:2)

部分答案

背景

要了解正在发生的事情,请考虑在级别上发生的事情 将2个单位十六进制数加在一起

如果2个十六进制十进制数字的总和加起来&lt; 10;结果与将2位十进制数加在一起完全相同:

x'4' + x'5' = x'9' ~ 9

但如果2位数加起来一个&gt; = 10,我们可以加x'6'来得到十进制等值

x'5' + x'6' = x'B'      and x'b'  + x'6' = x'11' ~ 5 + 6 = 11
x'8' + x'9' = x'11'     and x'11' + x'6' = x'17' ~ 8 + 9 = 17

实际公式(单位数级别)更复杂

if digit1 + digit2 < 10 (x'a')
   total = digit1 + digit2 + x'6' - x'6'
else
   total = digit1 + digit2 + x'6' - x'0'

十六进制加法可用于使用此公式

进行十进制加法
     Number_1 + Number_2 + x'66 66 66 66' - x'hi jk lm no'

h - &gt; o中的x'hi jk lm no' 0 6 。基本上,如果 Number_1.digit + number_2.digit&gt; = 10 ,那么h - &gt; o 0 否则将 6

示例:

 [00 00 01 23] + [00 00 02 20} + [66 66 66 66] - [66 66 66 66] = [00 00 03 43]
 [00 00 07 18] + [00 00 06 28} + [66 66 66 66] - [66 66 06 06] = [00 00 13 46]
 [00 00 01 83] + [00 00 02 91} + [66 66 66 66] - [66 66 66 06] = [00 00 04 74]

解释代码

以下4个陈述(来自前5个)计算: number_1 + Number_2 + x'66 66 66 66'

  00401229  add         eax,33333333h    ;  [00 00 01 23] + [33 33 33 33] = [33 33 34 56]eax  
  0040122E  add         edx,33333333h    ;  [00 00 02 20] + [33 33 33 33] = [33 33 35 53]edx
  00401234  mov         ebx,eax          ; copying eax to ebx   ; ebx = eax = 33 33 34 56

  00401238  add         eax,edx          ; [33 33 34 56]eax  + [33 33 35 53]edx = [66 66 69 A9]eax 
最后

最后的行也很容易

  00401241  and         ebx,22222222h        ; [F3 33 32 EA](ebx) & [22 22 22 22] = [22 22 22 22]
  00401247  lea         ebx,[ebx+ebx*2]      ;ebx = 66 66 66 66

数字x'6'表示为b'0110',即设置2比特。这更容易 设置/清除1位,即x'2'为b'0010',因此为22222222h。

因此,以下行计算x'hi jk lm no' / 3:

  00401241  and         ebx,22222222h        ; [F3 33 32 EA](ebx) & [22 22 22 22] = [22 22 22 22]

并且第二行将(x'hi jk lm no' / 3)乘以3给我们x'hi jk lm no';在位级别,它将0010转换为0110.

向后工作

查看前两行

 0040123C  shr         ebx,3                ; 3 >> [66 66 68 AC](ebx) =  [0C CC CD 15](ebx)
 0040123F  not         ebx                  ; [0C CC CD 15](ebx) NOT  ==>  [F3 33 32 EA](ebx)

右移3将'进位'移回2位(准备与x'2')。考虑在位级添加2位数:

 8 + 9 = b'1000' + b'1001' = b'10001' 

接下来我们需要为decimal adjustment

添加6
 b'10001' + b'0110' = b'10111'

如果你将b'1 0111'3位向右移动你得到b'0010'(x'2'),将其反转为b'1101' 准备好到x'22 22 22 22'已经讨论过这一步:

  00401241  and         ebx,22222222h        ; [F3 33 32 EA](ebx) & [22 22 22 22] = [22 22 22 22]

可能的问题

我怀疑代码会丢失顶部进位,所以

[50 00 00 01] + [50 00 00 01]

可能是[A0 00 00 02]而不是[00 00 00 02]。第二部分可以纠正这个???

如果数字以Comp-3开始并且右移4位,则不会出现问题