2017-02-25 84 views
0

我有以下函數需要3個雙重參數。在我的調試器中,當達到此功能的中斷時。檢查函數的參數我沒有看到3個雙重論點。在x86上如何將雙精度函數傳遞給函數

在x86平臺上的雙參數保存在棧上的功能?

下面是在WinDbg中的功能和拆卸。爲什麼我看不到在windbg中傳遞給函數的值爲Args to Child?

vector<double> calculate_quadratic(double a, double b, double c) 
    { 
     double discriminant = (b * b) - 4 * a * c; 
     vector<double>result; 

     try 
     { 
      if (discriminant < 0) 
       throw Bad_Value{}; 
      else 
      { 
       double d = sqrt(discriminant); 
       double px = (-b + d)/(2 * a); 
       double nx = (-b - d)/(2 * a); 

       result.push_back(px); 
       result.push_back(nx); 
      } 
     } 
     catch (Bad_Value) 
     { 
      cerr << "invalid value" << endl; 
     } 

     return result; 
    } 


    0:000> kb 
    # ChildEBP RetAddr Args to Child 
    00 003dfd2c 0126ad86 003dfe30 00000000 3ff00000 quadratic!calculate_quadratic 
    01 003dfe84 0126ba6e 00000001 0043d080 0043dd18 quadratic!main+0xc6 
    02 003dfe98 0126b8d0 ac1dec02 00000000 00000000 quadratic!invoke_main+0x1e 
    03 003dfef0 0126b76d 003dff00 0126ba88 003dff0c quadratic!__scrt_common_main_seh+0x150 
    04 003dfef8 0126ba88 003dff0c 772c336a 7efde000 quadratic!__scrt_common_main+0xd 
    05 003dff00 772c336a 7efde000 003dff4c 777f9f72 quadratic!mainCRTStartup+0x8 
    06 003dff0c 777f9f72 7efde000 77465726 00000000 kernel32!BaseThreadInitThunk+0xe 
    07 003dff4c 777f9f45 01261127 7efde000 00000000 ntdll!__RtlUserThreadStart+0x70 
    08 003dff64 00000000 01261127 7efde000 00000000 ntdll!_RtlUserThreadStart+0x1b 

    0:000> r 
    eax=003dfe30 ebx=003dfd48 ecx=acd07c23 edx=582e27d8 esi=003dfd50 edi=003dfd4c 
    eip=01268f70 esp=003dfd30 ebp=003dfe84 iopl=0   nv up ei pl nz ac po nc 
    cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b    efl=00000212 
    quadratic!calculate_quadratic: 
    01268f70 push ebp 

    0:000> dv /t /v 
    003dfd38   double a = 1 
    003dfd40   double b = -3 
    003dfd48   double c = 2 
    003dfd0c   double discriminant = 1.7499487580265442e+127 
    003dfcf4   struct Vector<double> result = struct Vector<double> 

傾倒頂框的ChildEBP我現在可以看到以相反的順序在堆棧上的參數 - 在這種情況下,我用10個三次,其被表示爲40240000億

0:000> kb 
# ChildEBP RetAddr Args to Child 
00 004cfac4 0017ad86 004cfbc8 00000000 40240000 quadratic!calculate_quadratic 

0:000> dd 004cfac4 
004cfac4 5a23da80 0017ad86 004cfbc8 00000000 
004cfad4 40240000 00000000 40240000 00000000 
004cfae4 40240000 ed0a64cf 00000000 00000000 

0:000> .formats 4024000000000000 
Evaluate expression: 
    Hex:  40240000`00000000 
    Decimal: 4621819117588971520 
    Octal: 0400440000000000000000 
    Binary: 01000000 00100100 00000000 00000000 00000000 00000000 00000000 00000000 
    Chars: @$...... 
    Time: Fri Dec 18 11:22:38.897 16246 (UTC - 5:00) 
    Float: low 0 high 2.5625 
    Double: 10 
+1

我不知道有關Windows,但在Linux上,有適用於System V應用程序二進制接口,其中寄存器XMM0到XMM7用於傳遞浮點參數。你也應該轉儲這些寄存器。 – overseas

+0

我期待在堆棧的頂部框架:00 003dfd2c 0126ad86 003dfe30 00000000 3ff00000二次calculate_quadratic ----我會嘗試你的建議.... – dcrearer

+0

@overseas你確定這是一個x86版本真(32位)? –

回答

3

的C/C++的默認調用約定是cdecl。在這個調用約定中,當爲x86構建時,參數會以相反的順序傳遞到堆棧上。當然,編譯器選項或函數裝飾可以覆蓋這種行爲。

看着你的WinDBG輸出,前三堆棧條目(參數以子)是:

003dfe30 00000000 3ff00000 

由於double爲64個位寬你只關注一個和你的論點一半。第一個條目看起來是EAX的內容......編譯器優化可能會在你的斷點觸發的時候將EAX推入堆棧?下一個值是00000000 3ff00000,即LE 3ff0000000000000 = 1(IEEE754),最左邊的參數和最後一個被傳遞到cdecl中的堆棧。

+0

但看看我的堆棧的頂部框架我沒有看到任何看起來像參數傳入的值。 – dcrearer

+0

@RbMm:除了你通過9個或更多浮點。當然這是非常不合理的。 – overseas

+0

@RbMm:這與[documentation](https://msdn.microsoft.com/en-us/library/zkwh89ks.aspx)有衝突。我很確定,至少使用[/fp:precise](https://msdn.microsoft.com/en-us/library/e7s85ffb.aspx),將浮點值傳遞到堆棧上(對於x86) 。 x64總是使用SSE單元。 – IInspectable

0

如何參數傳遞是依賴於編譯器和通常可以通過選擇或編譯器指令而改變。

如果用於傳遞浮點參數,大多數x86編譯器將使用x87 FPU堆棧(ST0-ST7寄存器)或SSE寄存器(XMM0-XMM7)。在MSVC上,這由/ arch和/ fp選項控制。

+1

'/ arch'和'/ fp'對調用約定沒有影響。如果您認爲調用代碼*必須知道將參數放在哪裏,那麼編譯器無法修改此行爲。當然,函數本身可能會使用這些寄存器,但它不能期望在那裏找到它的參數,因爲調用代碼不知道它應該將參數放在那裏。這就是調用約定,調用約定的規則並不靈活。 –