欢迎来到 嗅灵易学

零基础也能上手的脚本技术课,一对一答疑带你入门

我的一次Debug(续):音量调节函数浅析 (26千字)

我的一次Debug(续):音量调节函数浅析 (26千字)

我的一次Debug(续):音量调节函数浅析
这篇文字希望能回答一些朋友所询问的关于音量调节的细节问题。上篇文章中我只贴出了最关键的设置代码,也没有进一步解释。
另外,宽河朋友跟踪一个类似出问题的软件后,也贴了一段代码。我看了后觉得有点眼熟耶~~~随后比较NewPlay 4.01相关代码,竟然一模一样:)这是怎么回事,我不太明白……
解释代码是件困难的事情,还是用程序来描述吧。下面用了“类Delphi”来描述,因为源程序可能是Delphi写的,但由于编译优化,有些只好用寄存器描述,goto语句还不能避免。有些习惯还保留,如16进制还是用h后缀。不当的地方请多多指教为谢!
最后,我在测试时发现,上篇似乎将左声道和右声道写反了:( 尽管这对找静音原因不是一个问题,却不希望误导,特此提出。
==================================================
这个函数(过程)设置音量,包括静音。分析一下,可以知道参数一共有5个,栈中push了3个,寄存器中放了2个(eax, ecx)。下面要进一步解释和了解这些参数的意义。为了叙述方便,把栈参数称param1、param2、param3,寄存器参数称regeax、regecx。
先把变量的相关资料总结在下面供查询:
参数:
regeax为指针,通过它取一个变量作为参数调用sub_00477588
regecx为一个32位integer,为一个正整数,或FFFFFFFF。在NewPlay中总是FFFFFFFF。
param1为静音与否Mute(=1静音,=0取消静音)
param2是左声道值leftValue
param3是右声道值rightValue
局部变量:
[ebp-4]=regeax。4pEax
[ebp-8]=regecx。8Ecx
[ebp-9]byte型的boolean。9bResult;函数的返回值
[ebp-10h]指针,通过sub_00477588返回的值。10p
[ebp-11]byte类型的boolean,如果leftValue=-1就等于为true,否则0。11bNoRightValue
[ebp-12]byte类型的boolean,如果Mute=-1就等于为true,否则0。12bNoMute
局部变量之MIXERCONTROLDETAILS结构
[ebp-18]=paDetails;(这个关键指针指向[ebp-150h])
[ebp-1c]=cbDetails;
[ebp-20]=hwndOwner or cMultipleItems;
[ebp-24]=cChannels;
[ebp-28]=dwControlID;
[ebp-2c]=cbStuct;
[ebp-2c]=&MIXERCONTROLDETAILS;
[ebp-150]=右声道数值(right)。或是否mute(此时要cChannels=1)
[ebp-14c]=左声道数值(left)
[ebp-2c]到[ebp-0D4]为一个32位整数数组。d4IntArray[1..2Ah]。其中[ebp-0B8](B8int)是cChannel的默认值2
==================================================
下面是程序分析,先逐行把汇编写成“类Delphi”语言,再把“类Delphi”代码合并起来,脉络就清晰多了
* Referenced by a CALL at Addresses:
|:004920CD  , :0049A35D  , :0049A3C5  , :0049A407  , :0049A48C
|:0049A5E9  , :0049A745  , :0049CCFC
|
:00477A24 55                      push ebp
:00477A25 8BEC                    mov ebp, esp
:00477A27 81C4B0FEFFFF            add esp, FFFFFEB0
上面三句大概是Borland的习惯吧。经过这样处理,栈具有一定的布局:
[ebp+8]为从栈传的第一个参数的位置,[ebp+c]为栈传的第二个参数的位置,类推。
[ebp-4]为第一个局部变量的位置(如果这个局部变量是32位的话),类推。
........——locVar2—locVar1—EBPvalue(EBP指向这里)—RetAddr—1stParam—2ndParam——......栈顶(ESP指向这里)
                    局部变量区              EBP值                          返回地址  参数区                                      栈顶

:00477A2D 53                      push ebx
:00477A2E 56                      push esi
:00477A2F 57                      push edi
压栈
:00477A30 894DF8                  mov dword ptr [ebp-08], ecx
:00477A33 8945FC                  mov dword ptr [ebp-04], eax
:00477A36 C645F700                mov [ebp-09], 00
8Ecx:=ecx;
4pEax:=eax;
9bResult:=false;
:00477A3A 8B45FC                  mov eax, dword ptr [ebp-04]
:00477A3D 8B4028                  mov eax, dword ptr [eax+28]
:00477A40 E843FBFFFF              call 00477588
:00477A45 8945F0                  mov dword ptr [ebp-10], eax
:00477A48 837DF000                cmp dword ptr [ebp-10], 00000000
:00477A4C 0F848D020000            je 00477CDF
10p:=sub_00477588( ^(4pEax+28h) );
if 10p=nil then
  goto lblExit;
:00477A52 837DF8FF                cmp dword ptr [ebp-08], FFFFFFFF
:00477A56 7520                    jne 00477A78
:00477A58 8B45F0                  mov eax, dword ptr [ebp-10]
:00477A5B 8BB8B0000000            mov edi, dword ptr [eax+000000B0]
:00477A61 8B45F0                  mov eax, dword ptr [ebp-10]
:00477A64 57                      push edi
:00477A65 8D7008                  lea esi, dword ptr [eax+08]
:00477A68 8DBD2CFFFFFF            lea edi, dword ptr [ebp+FFFFFF2C]
:00477A6E B92A000000              mov ecx, 0000002A
:00477A73 F3                      repz
:00477A74 A5                      movsd
:00477A75 5F                      pop edi
:00477A76 EB31                    jmp 00477AA9
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00477A56(C)
|
:00477A78 8B45F0                  mov eax, dword ptr [ebp-10]
:00477A7B 8B80B4000000            mov eax, dword ptr [eax+000000B4]
:00477A81 8B55F8                  mov edx, dword ptr [ebp-08]
:00477A84 E817F9FFFF              call 004773A0
:00477A89 85C0                    test eax, eax
:00477A8B 741A                    je 00477AA7
:00477A8D 8BB8B0000000            mov edi, dword ptr [eax+000000B0]
:00477A93 57                      push edi
:00477A94 8D7008                  lea esi, dword ptr [eax+08]
:00477A97 8DBD2CFFFFFF            lea edi, dword ptr [ebp+FFFFFF2C]
:00477A9D B92A000000              mov ecx, 0000002A
:00477AA2 F3                      repz
:00477AA3 A5                      movsd
:00477AA4 5F                      pop edi
:00477AA5 EB02                    jmp 00477AA9
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00477A8B(C)
|
:00477AA7 33FF                    xor edi, edi
if 8Ecx=FFFFFFFFh then
begin
  for i:=1 to 2Ah do
    d4IntArray[i]:=^((10p+7)+i);
  edi:=^(10p+B0h);
end
else
begin
  eax:=sub_004773A0( ^(10p+B4h),8Ecx );
  if eax<>0 then
  begin
    for i:=1 to 2Ah do
      d4IntArray[i]:=^((eax+7)+i));
    edi:=^(eax+B0h);
  end
  else
    edi:=0;
end;
* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:00477A76(U), :00477AA5(U)
|
:00477AA9 85FF                    test edi, edi
:00477AAB 0F842E020000            je 00477CDF
if edi=0 then
  goto lblExit;
:00477AB1 33F6                    xor esi, esi
:00477AB3 837D10FF                cmp dword ptr [ebp+10], FFFFFFFF
:00477AB7 0F9445EF                sete byte ptr [ebp-11]
:00477ABB 837D08FF                cmp dword ptr [ebp+08], FFFFFFFF
:00477ABF 0F9445EE                sete byte ptr [ebp-12]
:00477AC3 C645F701                mov [ebp-09], 01
:00477AC7 E9DB000000              jmp 00477BA7
esi:=0;
if rightValue=FFFFFFFFh then
  11bNoRightValue:=true;
if Mute=FFFFFFFFh then
  12bNoMute:=true;
9bResult:=true;
goto lbl00477BA7;
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00477BBC(C)
|
:00477ACC 8BD6                    mov edx, esi
:00477ACE 8BC7                    mov eax, edi
:00477AD0 E8EBF6FFFF              call 004771C0
:00477AD5 8BD8                    mov ebx, eax
:00477AD7 85DB                    test ebx, ebx
:00477AD9 0F84C7000000            je 00477BA6
lbl00477AAC:
ebx:=sub_004771C0(esi,edi);//返回值ebx是个指针,[ebx+4]是dwControlID,[ebx+0Ch]为cChannel
if ebx<>0 then
begin
:00477ADF 8B4308                  mov eax, dword ptr [ebx+08]
:00477AE2 3D01000350              cmp eax, 50030001
:00477AE7 740B                    je 00477AF4
:00477AE9 3D02000120              cmp eax, 20010002
:00477AEE 0F85B2000000            jne 00477BA6
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00477AE7(C)
|
:00477AF4 8B430C                  mov eax, dword ptr [ebx+0C]
:00477AF7 83E002                  and eax, 00000002
:00477AFA 83F802                  cmp eax, 00000002
:00477AFD 0F84A3000000            je 00477BA6
:00477B03 C745D418000000          mov [ebp-2C], 00000018
:00477B0A 8B4304                  mov eax, dword ptr [ebx+04]
:00477B0D 8945D8                  mov dword ptr [ebp-28], eax
:00477B10 F7430C01000000          test [ebx+0C], 00000001
:00477B17 7609                    jbe 00477B22
:00477B19 C745DC01000000          mov [ebp-24], 00000001
:00477B20 EB09                    jmp 00477B2B
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00477B17(C)
|
:00477B22 8B8548FFFFFF            mov eax, dword ptr [ebp+FFFFFF48]
:00477B28 8945DC                  mov dword ptr [ebp-24], eax
  case ^(ebx+8) of
    20010002,5003001:
    begin
      eax:=^(ebx+Ch);
      if eax=00000002h then
        goto lbl00477BA6;
      cbStuct:=18h;
      dwControlID:=^(ebx+4h);
      if ^(ebx+Ch)>1 then
        cChannels:=1
      else
        cChannels:=B8int;//=2
      end;
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00477B20(U)
|
:00477B2B 33C0                    xor eax, eax
:00477B2D 8945E0                  mov dword ptr [ebp-20], eax
:00477B30 C745E404000000          mov [ebp-1C], 00000004
:00477B37 8D85B0FEFFFF            lea eax, dword ptr [ebp+FFFFFEB0]
:00477B3D 8945E8                  mov dword ptr [ebp-18], eax
      hwndOwner:=0;
      cbDetails:=4;
      paDetails:=@[ebp-150h];
:00477B40 817B0801000350          cmp dword ptr [ebx+08], 50030001
:00477B47 752F                    jne 00477B78
:00477B49 807DEF00                cmp byte ptr [ebp-11], 00
:00477B4D 7529                    jne 00477B78
:00477B4F 8B4510                  mov eax, dword ptr [ebp+10]
:00477B52 8985B0FEFFFF            mov dword ptr [ebp+FFFFFEB0], eax
:00477B58 837D0CFF                cmp dword ptr [ebp+0C], FFFFFFFF
:00477B5C 750B                    jne 00477B69
:00477B5E 8B4510                  mov eax, dword ptr [ebp+10]
:00477B61 8985B4FEFFFF            mov dword ptr [ebp+FFFFFEB4], eax
:00477B67 EB09                    jmp 00477B72
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00477B5C(C)
|
:00477B69 8B450C                  mov eax, dword ptr [ebp+0C]
:00477B6C 8985B4FEFFFF            mov dword ptr [ebp+FFFFFEB4], eax
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00477B67(U)
|
:00477B72 C645EF01                mov [ebp-11], 01
:00477B76 EB1C                    jmp 00477B94
* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:00477B47(C), :00477B4D(C)
|
:00477B78 817B0802000120          cmp dword ptr [ebx+08], 20010002
:00477B7F 7513                    jne 00477B94
:00477B81 807DEE00                cmp byte ptr [ebp-12], 00
:00477B85 750D                    jne 00477B94
:00477B87 8B4508                  mov eax, dword ptr [ebp+08]
:00477B8A 8985B4FEFFFF            mov dword ptr [ebp+FFFFFEB0], eax
:00477B90 C645EE01                mov [ebp-12], 01
      if [ebx+8]=50030001 then//50030001设置音量
      begin
        if not 11bNoRightValue then//如果右声道数据有定义(<>FFFFFFFFh)
        begin
          right:=rightValue;
          if leftValue=FFFFFFFFh then
            left:=rihtValue;
          else
            left:=leftValue;
          11bNoRightValue:=true;
        end
      end
      else
        begin
        if [ebx+8]=20010002 then//20010002设置静音
        begin
          if not 12bNoMute then
          begin
            right:=Mute;
            12bNoMute:=true;
          end;
        end;
      end;
* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:00477B76(U), :00477B7F(C), :00477B85(C)
|
:00477B94 6A00                    push 00000000
:00477B96 8D45D4                  lea eax, dword ptr [ebp-2C]
:00477B99 50                      push eax
:00477B9A 8B45FC                  mov eax, dword ptr [ebp-04]
:00477B9D 8B4030                  mov eax, dword ptr [eax+30]
:00477BA0 50                      push eax
* Reference To: winmm.mixerSetControlDetails, Ord:0000h
                                  |
:00477BA1 E852F0FFFF              Call 00476BF8
      mixerSetControlDetails(^(4pEax+30h),@MIXERCONTROLDETAILS,0);
    end;
  else
    begin
* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:00477AD9(C), :00477AEE(C), :00477AFD(C)
|
:00477BA6 46                      inc esi
lbl00477BA6:
      esi:=esi+1;
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00477AC7(U)
|
:00477BA7 807DEF00                cmp byte ptr [ebp-11], 00
:00477BAB 7406                    je 00477BB3
:00477BAD 807DEE00                cmp byte ptr [ebp-12], 00
:00477BB1 750F                    jne 00477BC2
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00477BAB(C)
|
:00477BB3 8BC7                    mov eax, edi
:00477BB5 E812F6FFFF              call 004771CC
:00477BBA 3BF0                    cmp esi, eax
:00477BBC 0F8C0AFFFFFF            jl 00477ACC
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00477BB1(C)
|
:00477BC2 807DEE00                cmp byte ptr [ebp-12], 00
:00477BC6 0F8513010000            jne 00477CDF
:00477BCC 837DF8FF                cmp dword ptr [ebp-08], FFFFFFFF
:00477BD0 0F8409010000            je 00477CDF
lbl00477BA7:
      if 11NoRightValue then
        if not 12bNoMute then
          goto lb00477BC2;
      if esi<sub_004771CC(edi) then
        goto lbl00477ACC;
lbl00477BC2:
      if not 12bNoMute then
        goto lblExit;
      if 8Ecx=FFFFFFFFh then
        goto lblExit;
:00477BD6 8B45F0                  mov eax, dword ptr [ebp-10]
:00477BD9 8BB8B0000000            mov edi, dword ptr [eax+000000B0]
:00477BDF 8B45F0                  mov eax, dword ptr [ebp-10]
:00477BE2 57                      push edi
:00477BE3 8D7008                  lea esi, dword ptr [eax+08]
:00477BE6 8DBD2CFFFFFF            lea edi, dword ptr [ebp+FFFFFF2C]
:00477BEC B92A000000              mov ecx, 0000002A
:00477BF1 F3                      repz
:00477BF2 A5                      movsd
:00477BF3 5F                      pop edi
:00477BF4 85FF                    test edi, edi
:00477BF6 0F84E3000000            je 00477CDF
:00477BFC 33F6                    xor esi, esi
:00477BFE E9C7000000              jmp 00477CCA
      for i:=1 to 2Ah do
        d4IntArray[i]:=^((10p+7)+i));
      edi:=^(10p+B0h);
      if edi=0 then
        goto lblExit;
      esi:=0
      goto lbl00477CCA;
    end;
  end;
end;
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00477CD9(C)
|
:00477C03 8BD6                    mov edx, esi
:00477C05 8BC7                    mov eax, edi
:00477C07 E8B4F5FFFF              call 004771C0
:00477C0C 8BD8                    mov ebx, eax
:00477C0E 8B4308                  mov eax, dword ptr [ebx+08]
:00477C11 3D01000171              cmp eax, 71010001
:00477C16 740B                    je 00477C23
:00477C18 3D01000170              cmp eax, 70010001
:00477C1D 0F85A6000000            jne 00477CC9
lbl00477C03;
ebx:=sub_4771C0(esi,edi);
case ^(ebx+8) of
  7101001,70010001:
  begin
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00477C16(C)
|
:00477C23 C745D418000000          mov [ebp-2C], 00000018
:00477C2A 8B4304                  mov eax, dword ptr [ebx+04]
:00477C2D 8945D8                  mov dword ptr [ebp-28], eax
:00477C30 8B430C                  mov eax, dword ptr [ebx+0C]
:00477C33 F7C001000000            test eax, 00000001
:00477C39 7609                    jbe 00477C44
:00477C3B C745DC01000000          mov [ebp-24], 00000001
:00477C42 EB09                    jmp 00477C4D
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00477C39(C)
|
:00477C44 8B9548FFFFFF            mov edx, dword ptr [ebp+FFFFFF48]
:00477C4A 8955DC                  mov dword ptr [ebp-24], edx
    cbStuct:=18h;
    dwControlID:=^(ebx+4h);
    eax:=^(ebx+Ch);
    if eax>1 then
      cChannels:=1
    else
      cChannels:=B8int;
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00477C42(U)
|
:00477C4D 83E002                  and eax, 00000002
:00477C50 83F802                  cmp eax, 00000002
:00477C53 7508                    jne 00477C5D
:00477C55 8B4310                  mov eax, dword ptr [ebx+10]
:00477C58 8945E0                  mov dword ptr [ebp-20], eax
:00477C5B EB05                    jmp 00477C62

注意:上传附件及图片大小不得大于30M。

⚠️ 版权声明:
本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途
未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。

0 0 0 举报
复制成功