简体   繁体   English

为什么在打印浮点数时需要将相同的值 +4 压入?

[英]Why do I need to push the same value +4 when printing a float?

I have been trying to print out a float value in FASM for a pretty long time until I finally found a solution, it worked but, why is it like that?很长一段时间以来,我一直试图在 FASM 中打印一个浮点值,直到我终于找到了一个解决方案,它起作用了,但是,为什么会这样呢? On a C program I made the assembly code generated by x64dbg was something like this:在一个 C 程序上,我让 x64dbg 生成的汇编代码是这样的:

mov dword ptr ss:[esp+1C],eax
fld st(0), dword ptr ss:[esp+1C] ;<--- focusing on these 2
fstp qword ptr ss:[esp+4],st(0)  ;<---
mov dword ptr ss:[esp],c.404000
call <JMP.&printf>

I thought the fact fld loaded the float value into st(0) and fstp loaded the st(0) value on an address, basically, quite obvious so I used to try things like:我认为事实fld将浮点值加载到 st(0) 中,而fstp将 st(0) 值加载到一个地址上,基本上,非常明显,所以我曾经尝试过这样的事情:

format PE
entry start

include '%include%\win32a.inc'

section '.text' code readable executable
start:
fld dword ptr dVal
fstp qword ptr dVal2
push msg
call [printf]
call [getchar]
call [exit]

section '.idata' import data readable
library msvcrt, 'msvcrt.dll'

import msvcrt, printf, 'printf'\
exit, 'exit', getchar, 'getchar'

section '.bss' data readable writeable
dVal2 dq ?

section '.data' data readable
msg db '%f',10,13,0
dVal dq 3.14

Which after many tries, rendered me crashes or results like 0 or random numbers that have nothing to do with what I wanted.经过多次尝试,这让我崩溃或结果如 0 或与我想要的无关的随机数。 However, after so much research I finally found out that I could simply do something like然而,经过这么多的研究,我终于发现我可以简单地做一些像

...
section '.text' code readable executable
start:
fld dword ptr dVal
fstp qword ptr dVal2
push dword ptr dVal2+4
push dword ptr dVal2
push msg
call [printf]
call [getchar]
call [exit]
...

or just要不就

...
section '.text' code readable executable
start:
push dword ptr dVal+4
push dword ptr dVal
push msg
call [printf]
call [getchar]
call [exit]
...

Why do I need to push the same value +4 before printing a float value?为什么我需要在打印浮点值之前将相同的值 +4 压入? And what essentially is the REAL4 value from MASM? MASM 的 REAL4 值本质上是什么?

The printf function can only print 64 bit floats (double). printf function 只能打印 64 位浮点数(双精度)。 Such a double comprises 8 bytes.这样的双精度包含 8 个字节。 Either push this value onto the stack by storing to the stack from the FPU:通过从 FPU 存储到堆栈来将此值压入堆栈:

sub     esp, 8           ; make space for the double
fstp    qword ptr [esp]  ; store double into that space
push    OFFSET msg
call    [printf]

or push to the stack in two steps of 4 bytes each:或分两步入栈,每步 4 字节:

fstp    [dVal2]          ; store double to global/static variable
push    dword ptr [dVal2+4]    ; push high half of double
push    dword ptr [dVal2]      ; push low half of double
push    OFFSET msg
call    [printf]

Note that as the stack grows down, we have to push the high 4 bytes before the low 4 bytes.请注意,随着堆栈向下增长,我们必须将高 4 字节压入低 4 字节之前。 Two separate pushes are required as you can only push 4 bytes at a time, but a double is 8 bytes.需要两次单独的推送,因为您一次只能推送 4 个字节,但 double 是 8 个字节。


Assuming you declared dVal2 as a qword like in the question, that will imply a size for fstp [dVal2] .假设您将dVal2声明为问题中的 qword,这将意味着fstp [dVal2]的大小。 fstp can also convert to dword (float) or store as the raw 10-byte internal format used in x87 registers. fstp还可以转换为双字(浮点)或存储为 x87 寄存器中使用的原始 10 字节内部格式。 That's why we needed fstp qword ptr [esp] since [esp] doesn't imply an operand size.这就是我们需要fstp qword ptr [esp]的原因,因为[esp]并不意味着操作数的大小。

As always, to access storage near a data label with a size different from the first item after that label, MASM needs you to override the size or it will complain about a mismatch, thus push dword ptr [dVal2+4] , because push qword ptr is only available in 64-bit mode.与往常一样,要访问数据 label 附近的存储,其大小与 label 之后的第一项不同,MASM 需要您覆盖大小,否则它将抱怨不匹配,因此push dword ptr [dVal2+4] ,因为push qword ptr仅在 64 位模式下可用。 (Where it would be passed in XMM1 as the 2nd arg to a function.) (它将在 XMM1 中作为第二个参数传递给 function。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM