Сейчас на форуме: tyns777, bezumchik, Lohmaty (+7 невидимых)

 eXeL@B —› Вопросы новичков —› Опознать стандартную функцию TurboPascal
Посл.ответ Сообщение

Ранг: 431.7 (мудрец), 390thx
Активность: 0.730.32
Статус: Участник

Создано: 11 марта 2019 06:26 · Поправил: dosprog
· Личное сообщение · #1

Ковыряю старинную программку (для DOS'а).
Написана изначально на какой-то из старых версий TurboPascal.

Интересует в той программке конкретно одна функция,
которую IDA определила так:

Code:
  1. ; =============== S U B R O U T I N E =======================================
  2.  
  3. ; Attributes: bp-based frame
  4.  
  5. sub_14C  proc near ; CODE XREF: sub_1A3+Fp sub_1A3+21p ...
  6.  
  7. var_1 = byte ptr -1
  8. arg_0 = word ptr  4
  9. arg_2 = word ptr  6
  10. arg_4 = word ptr  8
  11.  
  12.  push  bp
  13.  mov   bp, sp
  14.  sub   sp, 2
  15.  mov   ax, word_27B4
  16.  xor   dx, dx
  17.  call  @Real$q7Longint ; Real(x: Longint{DX:AX}): Real
  18.  mov   cx, [bp+arg_0]
  19.  mov   si, [bp+arg_2]
  20.  mov   di, [bp+arg_4]
  21.  call  @$brdiv$q4Realt1 ; Real(AX:BX:DX)/=Real(CX:SI:DI)
  22.                        ; Real(CX:SI:DI)=Real(AX:BX:DX)%Real(CX:SI:DI)
  23.  call  @Frac$q4Real    ; Frac(x: Real): Real
  24.  mov   cx, 2182h
  25.  mov   si, 0DAA2h
  26.  mov   di, 490Fh
  27.  call  @$brmul$q4Realt1 ; Real(AX:BX:DX)*=Real(CX:SI:DI)
  28.  
  29. ;????????????????????????????????????
  30.  call  @Sin$q4Real     ; Sin(x: Real): Real
  31. ;????????????????????????????????????
  32.  
  33.  and   dh, 7Fh
  34.  mov   cx, 87h ; 'ç'
  35.  xor   si, si
  36.  mov   di, 4800h
  37.  call  @$brmul$q4Realt1 ; Real(AX:BX:DX)*=Real(CX:SI:DI)
  38.  call  @Round$q4Real   ; Round(x: Real): Longint
  39.  mov   [bp+var_1], al
  40.  mov   al, [bp+var_1]
  41.  mov   sp, bp
  42.  pop   bp
  43.  retn    6
  44. sub_14C         endp
  45.  
  46. ;;;.................
  47. ;----------------------------------------------------------------------------
  48. ; [00000074 BYTES: COLLAPSED FUNCTION Sin(Real). PRESS KEYPAD "+" TO EXPAND]
  49.  
  50. seg006:0918 ; Sin(x: Real): Real
  51. seg006:0918 ; Attributes: library function
  52. seg006:0918
  53. seg006:0918 ; Sin(Real)
  54. seg006:0918 @Sin$q4Real proc far  ; CODE XREF: sub_14C+31P
  55. seg006:0918     mov     cx, 2181h
  56. seg006:091B     mov     si, 0DAA2h
  57. seg006:091E     mov     di, 0C90Fh
  58. seg006:0921     call    __RealAdd
  59. seg006:0924     or      al, al
  60. seg006:0926     jz      short @Cos$q4Real ; Cos(x: Real): Real
  61. seg006:0928     xor     dh, 80h
  62. seg006:092B
  63. seg006:092B ; Cos(Real)
  64. seg006:092B @Cos$q4Real: ; CODE XREF: Sin(Real)+Ej
  65. seg006:092B     cmp     al, 6Ch ; 'l' ; Cos(x: Real): Real
  66. seg006:092D     jb      short locret_1C4B
  67. seg006:092F     mov     cx, 2183h
  68. seg006:0932     mov     si, 0DAA2h
  69. seg006:0935     mov     di, 490Fh
  70. seg006:0938     push    dx
  71. seg006:0939     and     dh, 7Fh
  72. seg006:093C     call    __RealCmp
  73. seg006:093F     pop     dx
  74. seg006:0940     jb      short loc_1C12
  75. seg006:0942     call    sub_1B0C
  76. seg006:0945     push    di
  77. seg006:0946     push    si
  78. seg006:0947     push    cx
  79. seg006:0948     push    cs
  80. seg006:0949     call    near ptr @Frac$q4Real ; Frac(x: Real): Real
  81. seg006:094C     pop     cx
  82. seg006:094D     pop     si
  83. seg006:094E     pop     di
  84. seg006:094F     call    sub_1B02
  85. seg006:0952
  86. seg006:0952 loc_1C12: ; CODE XREF: Sin(Real)+28j
  87. seg006:0952     test    dh, 80h
  88. seg006:0955     jz      short loc_1C1A
  89. seg006:0957     call    sub_1AEE
  90. seg006:095A
  91. seg006:095A loc_1C1A: ; CODE XREF: Sin(Real)+3Dj
  92. seg006:095A     dec     cl
  93. seg006:095C     call    __RealCmp
  94. seg006:095F     pushf
  95. seg006:0960     jb      short loc_1C25
  96. seg006:0962     call    sub_1AF8
  97. seg006:0965
  98. seg006:0965 loc_1C25: ; CODE XREF: Sin(Real)+48j
  99. seg006:0965     dec     cl
  100. seg006:0967     call    __RealCmp
  101. seg006:096A     jb      short loc_1C34
  102. seg006:096C     inc     cl
  103. seg006:096E     or      dh, 80h
  104. seg006:0971     call    __RealAdd
  105. seg006:0974
  106. seg006:0974 loc_1C34:  ; CODE XREF: Sin(Real)+52j
  107. seg006:0974     cmp     al, 6Ch ; 'l'
  108. seg006:0976     jb      short loc_1C41
  109. seg006:0978     mov     di, 98Ch
  110. seg006:097B     mov     cx, 7
  111. seg006:097E     call    sub_1EF7
  112. seg006:0981
  113. seg006:0981 loc_1C41:  ; CODE XREF: Sin(Real)+5Ej
  114. seg006:0981     popf
  115. seg006:0982     jb      short locret_1C4B
  116. seg006:0984     or      al, al
  117. seg006:0986     jz      short locret_1C4B
  118. seg006:0988     xor     dh, 80h
  119. seg006:098B
  120. seg006:098B locret_1C4B:  ; CODE XREF: Sin(Real)+15j
  121. seg006:098B               ; Sin(Real)+6Aj ...
  122. seg006:098B                 retf
  123. seg006:098B @Sin$q4Real     endp


Собственно, вопрос по той функции, которую IDA обозвала как @Sin$q4Real(x), якобы она из RTL.
Но RTL используется, видимо, кастомная, не от NorbertJuffa.

И похоже, что то не sin(x) вовсе.

Для справок дальше выложу RTL-ную fsin.asm от TurboPascal 7...



Ранг: 431.7 (мудрец), 390thx
Активность: 0.730.32
Статус: Участник

Создано: 11 марта 2019 06:33 · Поправил: dosprog
· Личное сообщение · #2

[продолжение]


Файл fsin.asm от TurboPascal 7 стандартной RTL, для сравнения:

Code:
  1. ; *******************************************************
  2. ; * *
  3. ; * Turbo Pascal Runtime Library Version 7.0 *
  4. ; * Real Sine/Cosine *
  5. ; * *
  6. ; * Copyright (C) 1989-1993 Norbert Juffa *
  7. ; * *
  8. ; *******************************************************
  9.  
  10.              TITLE   FPSIN
  11.  
  12. CODE         SEGMENT BYTE PUBLIC
  13.  
  14.              ASSUME  CS:CODE
  15.  
  16.              EXTRN   RealAdd:NEAR,RealSub:NEAR,RealPoly:NEAR,RealMulNoChk:NEAR,
  17.              EXTRN   HaltError:NEAR,RealTrunc:NEAR,RealMul:NEAR,RealFloat:NEAR
  18.              EXTRN   RealReduceMP:NEAR,RFrac:FAR,RealMulFNoChk:NEAR
  19.  
  20.              PUBLIC  RSin,RCos
  21.  
  22. RCos         PROC    FAR
  23.              PUSH    BP                ; save caller's frame pointer
  24.              AND     DH, 7Fh           ; abs(x), since cos (x) = cos (abs(x))
  25.              MOV     BP, 2             ; load function code for cosine
  26.              JMP     $cos_entry        ; goto sine/cosine computation
  27. RCos         ENDP
  28.  
  29.              ALIGN   4
  30.  
  31. RSin         PROC    FAR
  32.              PUSH    BP                ; save caller's frame pointer
  33.              XOR     BP, BP            ; load function code for sine
  34. $cos_entry:  MOV     CH, 80h           ; load mask to extract sign bit
  35.              AND     CH, DH            ; extract sign bit
  36.              XOR     DH, CH            ; x := abs(x)
  37.              PUSH    CX                ; save sign
  38. $value_ok:   MOV     CX, 04E81h        ; load
  39.              MOV     SI, 0836Eh        ; real constant
  40.              MOV     DI, 022F9h        ; 4/pi
  41.              CMP     AL, 9Fh           ; x >= 2^30 ?
  42.              JAE     $big_val          ; x/(pi/4) too big to be stored in long
  43.              PUSH    AX                ; save x
  44.              PUSH    BX                ; on
  45.              PUSH    DX                ; stack
  46.              CALL    RealMulFNoChk     ; compute x/(pi/4)
  47.              XOR     CH, CH            ; signal truncation desired
  48.              CALL    RealTrunc         ; n = Trunc (x/(pi/4))
  49.              ROR     AL, 1             ; if quadrant odd, set CF=1
  50.              ROL     AL, 1             ; restore register, CF=1 if odd quadrant
  51.              ADC     AX, 0             ; increment quadrant
  52.              ADC     DX, 0             ; if quadrant odd
  53.              ADD     BP, AX            ; q := quadrant + flag
  54.              CALL    RealFloat         ; convert quadrant to REAL value
  55.              POP     DI                ; get
  56.              POP     SI                ; back
  57.              POP     CX                ; x
  58.              TEST    BP, 3             ; determine octants that use cos,sin
  59.              PUSHF                     ; save sin/cos flag
  60.              PUSH    BP                ; save q
  61.              MOV     BP, OFFSET c1     ; pointer to reduction constant table
  62.              CALL    RealReduceMP      ; compute x + n*(pi/2) to full precision
  63.              MOV     CX, 5             ; use five coefficients
  64.              XOR     SI, SI            ; signal P(x²)*x+x wanted
  65.              POP     BP                ; get back q
  66.              POPF                      ; get back sin/cos flag
  67.              JPE     $sine             ; octants 0, 3, 4, 7 take sine
  68. $cosine:     MOV     DI,OFFSET CS_COEFF; pointer to 1st coeff. of cos approx.
  69.              INC     SI                ; signal P(x²) wanted
  70.              CALL    RealPoly          ; P(x²) in DX:BX:AX
  71.              MOV     CX, 00081h        ; load
  72.              XOR     SI, SI            ; floating-point
  73.              MOV     DI, SI            ; constant 1.0
  74.              CALL    RealAdd           ; 1 + P(x²)
  75.              JMP     $make_sign        ; put appropriate sign on result
  76. $sine:       MOV     DI,OFFSET SN_COEFF; pointer to 1st coeff. of sin approx.
  77.              CALL    RealPoly          ; P(x²)*x+x in DX:BX:AX
  78. $make_sign:  POP     CX                ; get sign mask
  79.              INC     BP                ; determine if
  80.              TEST    BP, 4             ; result has to negated
  81.              JZ      $ende             ; result ok
  82.              XOR     CH, 80h           ; negate sign flag
  83. $ende:       POP     BP                ; restore caller's frame pointer
  84.              OR      AL, AL            ; result zero ?
  85.              JZ      $end_sin          ; yes, done
  86.              XOR     DH, CH            ; make sign bit
  87. $end_sin:    RET                       ; done
  88.  
  89. $big_val:    SUB     CL, 3             ; 1/(2*pi) in DI:SI:CX
  90.              CALL    RealMulNoChk      ; x/(2*pi)
  91.              CALL    RFrac             ; frac (x/(2*pi))
  92.              MOV     CX, 02183h        ; load
  93.              MOV     SI, 0DAA2h        ; constant
  94.              MOV     DI, 0490Fh        ; 2*pi
  95.              CALL    RealMulNoChk      ; 2*pi * frac (x/(2*pi)) = remainder
  96.              JMP     $value_ok         ; reduction to 0..2*pi done
  97.  
  98. SN_COEFF     DB      067h,               0B1h,0D4h  ; -2.476053850842e-8
  99.              DB      06Eh,05Ch,08Bh,0B6h,0EBh,038h  ; 2.755533965768e-6
  100.              DB      074h,0B5h,09Ch,0FCh,00Ch,0D0h  ; -1.984126372865e-4
  101.              DB      07Ah,044h,086h,088h,088h,008h  ; 8.333333325083e-3
  102.              DB      07Eh,0A9h,0AAh,0AAh,0AAh,0AAh  ; -1.666666666663e-1
  103. CS_COEFF     DB      06Bh,               0C7h,091h  ; -2.715314622037e-7
  104.              DB      071h,034h,0B7h,0A1h,006h,050h  ; 2.479862035332e-5
  105.              DB      077h,02Eh,00Ah,058h,00Bh,0B6h  ; -1.388887879411e-3
  106.              DB      07Ch,018h,0A0h,0AAh,0AAh,02Ah  ; 4.166666651281e-2
  107.              DB      07Fh,0EFh,0FFh,0FFh,0FFh,0FFh  ; -4.999999999923e-1
  108.  
  109. C1           DB      080h,000h,000h,000h,00Fh,0C9h  ; pi/4-eps =
  110. C2           DB      070h,0c2h,068h,021h,0a2h,0dah  ; eps =
  111.  
  112. RSIN         ENDP
  113.  
  114.              ALIGN   4
  115.  
  116. CODE         ENDS
  117.  
  118.              END
  119.  




Ну и собственно, в чём затык - переписал функцию на Си
- Всё работает, за исключением функции sin(x), по которой как раз и были вопросы.
В тексте комментариями обозначены места, где затык:

Code:
  1.  
  2. #include <stdio.h>
  3. #include <math.h>
  4.  
  5. /*-------------------------------------------------------*/
  6. unsigned int    dwWord12result  = 0x17AD ;
  7. unsigned int    iPersent        ;
  8.  
  9. /*----------------------------------------------------*/
  10. unsigned int get_persent (double factor)            /* sub_14C originally */
  11. {
  12. unsigned int  result = 0;
  13. double compat_double;
  14.  
  15.      compat_double = (double) dwWord12result              ;
  16.      compat_double = compat_double / factor               ;
  17.      compat_double = compat_double - floor(compat_double) ; /*Frac()*/
  18.      compat_double = compat_double * 3.14159265358979     ; /*PI*/
  19.                                            
  20. /*  here compat_double = 2.71193340012178 */
  21.  
  22.     /********************************************************************
  23.       ??? ERROR   f(2.71193340012178) must be -0.909107744182620 !!!!???)
  24.      ********************************************************************
  25.      */
  26.      compat_double = sin( compat_double  )                 ;
  27.  
  28. /* must be -0.909107744182620 ????????? */
  29. #if 0
  30.   compat_double = -0.909107744182620;
  31. #endif
  32.  
  33.      if(compat_double<0 ) compat_double=-compat_double    ;
  34.      compat_double = compat_double * 100                  ;
  35.      result        = (unsigned int) (compat_double+0.5)   ;
  36.      result        = result & 0xFF                        ;
  37.  
  38. return (result);
  39. }
  40.  
  41. /*-------------------------------------------------------------------------*/
  42. void main(void)
  43. {
  44.   iPersent       = get_persent ( 23.6884365000005 );
  45.  
  46.   /***********************************
  47.    Here error - iPersent must be = 91  , ... but it is 42...
  48.   ************************************/
  49.  
  50.   printf("Calculated: %i%%",iPersent);
  51. }


- Эта тестовая программа, будучи запущенной, должна написать:

Calculated: 91%

но вместо этого пишет:

Calculated: 42%

Трассируя оригинальную программу и тестовый пример, вижу промежуточные результаты совпадающими вплоть до вызова функции sin()

Если в тестовом примере вместо "#if 0" написать "#if 1", то функция get_persent (double factor) вернёт 91, как ей и положено.
...


То, что функция обозвана как sin(x) неверно, подтверждается тем,
что вызов sin(2.71) и на Си, и на Паскале даёт одинаковый результат, примерно 0.415.

Что и приводит по итогу к результату 42% вместо 91%.

Но вот что это за функция в действительности, мне пока определить не удалось, сходу.





Ранг: 419.0 (мудрец), 647thx
Активность: 0.460.51
Статус: Участник
"Тибериумный реверсинг"

Создано: 11 марта 2019 09:09
· Личное сообщение · #3

dosprog пишет:
что то не sin(x) вовсе.

cos(x)? tg, ctg



Ранг: 431.7 (мудрец), 390thx
Активность: 0.730.32
Статус: Участник

Создано: 11 марта 2019 09:48 · Поправил: dosprog
· Личное сообщение · #4

Проверял.. как вечерком перед сном сел глянуть программульку, так и загляделся уже.
Психану и просто воспроизведу оригинальную функцию.
..С этим их нестрандартным Real'ом один головнякъ..





Ранг: 419.0 (мудрец), 647thx
Активность: 0.460.51
Статус: Участник
"Тибериумный реверсинг"

Создано: 11 марта 2019 10:16
· Личное сообщение · #5

dosprog пишет:
..С этим их нестрандартным

load действительно различаются,но по числам функи очень похожи
Code:
  1. MOV     CX, 02183h        ; load
  2.              MOV     SI, 0DAA2h        ; constant
  3.              MOV     DI, 0490Fh        ; 2*pi
  4.              CALL    RealMulNoChk      ; 2*pi * frac (x/(2*pi)) = remainder

Code:
  1. seg006:0918     mov     cx, 2181h
  2. seg006:091B     mov     si, 0DAA2h
  3. seg006:091E     mov     di, 0C90Fh
  4. seg006:0921     call    __RealAdd

RealMulNoChk == __RealAdd?



Ранг: 431.7 (мудрец), 390thx
Активность: 0.730.32
Статус: Участник

Создано: 11 марта 2019 10:36 · Поправил: dosprog
· Личное сообщение · #6

ELF_7719116 пишет:
load действительно различаются,но по числам функи очень похожи


Та константа это PI. Только и всего.. Так, наверное, и IDA пыталась опознавать эту функцию.

ELF_7719116 пишет:
RealMulNoChk == __RealAdd?


Не.. RealMul это умножение..

Функции разные, однозначно.

В стандартной RTL пытался искать что-то похожее, в том числе и по этим константам,
но ничего похожего нет.

.. Это был у паскальщиков в 90-х такой фетиш - подцепляли всякие самодельные RTL'ы.
Считалось признаком определённой крутости, - но иногда потом эта крутость выливалась в непонятные глюки софта.





Ранг: 39.4 (посетитель), 9thx
Активность: 0.01=0.01
Статус: Участник

Создано: 11 марта 2019 10:49
· Личное сообщение · #7

Begin
WriteLn(Cos(2.71));
End.

---------------
Borland Pascal Version 7.0 Copyright (c) 1983,92 Borland International
-9.0830066636E-01

| Сообщение посчитали полезным: dosprog

Ранг: 431.7 (мудрец), 390thx
Активность: 0.730.32
Статус: Участник

Создано: 11 марта 2019 11:03 · Поправил: dosprog
· Личное сообщение · #8

2nd пишет:
Begin
WriteLn(Cos(2.71));
End.


)) Точно. И ведь пробовал, вплоть до тангенсов, - видно, было уже поздно..

Проверил - всё работает.

.. Ну, бывает..




 eXeL@B —› Вопросы новичков —› Опознать стандартную функцию TurboPascal
Эта тема закрыта. Ответы больше не принимаются.
   Для печати Для печати