Windows 在调用asm函数之前,是否在C中调用printf会产生神秘的副作用?

Windows 在调用asm函数之前,是否在C中调用printf会产生神秘的副作用?,windows,gcc,assembly,x86,nasm,Windows,Gcc,Assembly,X86,Nasm,该程序必须按照用户提供的精度计算pi。 calculate_pi()函数是用NASM编写的。 有人能给我解释一下为什么这行被评论了吗 //printf("accuracy: %.15f\n", precision); //<- This line 样本输出: 我正在使用: NASM版本2.11.06于2014年10月20日编译 gcc(MinGW.org gcc-6.3.0-1)6.3.0 编译和汇编命令: nasm -o pi.o -f coff pi.asm gcc

该程序必须按照用户提供的精度计算pi。 calculate_pi()函数是用NASM编写的。 有人能给我解释一下为什么这行被评论了吗

//printf("accuracy: %.15f\n", precision);       //<- This line
样本输出:

我正在使用:

  • NASM版本2.11.06于2014年10月20日编译
  • gcc(MinGW.org gcc-6.3.0-1)6.3.0
编译和汇编命令:

nasm -o pi.o -f coff pi.asm
gcc pi.o pi_interface.c -o projekt.exe -Wall -Wextra

我认为您访问的函数arg不正确,偏移了4个字节。制作堆栈帧时,第一个参数位于
[ebp+8]
,但您是从
[ebp+12]
加载的。(这适用于在堆栈上传递参数的所有调用约定。我认为默认情况下,32位mingw对
double
执行此操作。)

这意味着作为
precision
使用的
double
值在8字节arg插槽上方的堆栈上有4个高字节。这解释了为什么调用方的更改会影响函数的行为,以及为什么可以得到一个无限循环:如果加载的字节恰好代表一个非常小的
double
,则循环永远不会退出

低4字节(尾数的32个最低有效位)来自调用者传递的内容的前4个字节


通过查看寄存器并注意到加载的值不是调用方传递的值,您可以很容易地通过调试器找到这一点。此外,@Ped7g建议只在一个简单的asm函数中返回
精度
,这也会发现问题。

这不是一种非常方便用户指定精度的方法。正确数字的数量可能更多。请解释它以何种方式不能正常工作。似乎汇编函数没有遵循目标平台的正确调用约定,在汇编调用之前使用
printf
code,您会很幸运,意外地选择了正确的值。尝试在调试器中检查两者之间的条目状态差异。您甚至没有显示
calculate\u pi
函数的声明,也没有显示它的asm源代码,您认为我们在这里是神谕吗D(因为在某一点上,你甚至没有接近于浪费每个人的时间而投反对票)@Ped7g:正确的回答是,基于这个原因投反对票。由于缺少MCVE而进行向下投票是一种选择,但如果不进行实际的关闭投票(除非你将关闭投票保存为一个副本),那么这样做没有什么意义。Leo:你的问题与相关来源(你可以创建占位符程序集,它只会返回参数精度),构建它,确保它显示相同的问题,然后对完整的可构建源代码+您的目标平台+如何构建可执行文件提出疑问,这样任何有权访问类似平台的人都可以尝试重现您的问题@彼得·科尔德斯:我把“接近”的投票保留到OP无法沟通,也无法改善Q的时刻。一旦Q被关闭,在我看来,很难让它恢复生机。
;   arctg(1)=a
;   tg(arctg(1))=tg(a)
;   atan(x) = x - x^3/3 + x^5/5 - x^7/7 + x^9/9..
;   PI/4 = atan(1) = 1 - 1/3 + 1/5 - 1/7 + 1/9...
;   PI = (4/1) - (4/3) + (4/5) - (4/7) + (4/9) - (4/11) + (4/13) - (4/15) ...


section .text use32

global  _calculate_pi

_calculate_pi:

%idefine    a   [ebp+12]


;ramka stosu
push    ebp
mov ebp, esp

;ustawianie zmiennych
fld qword [const_wynik]
fstp qword [wynik]

fld qword [const_licznik]
fstp qword [licznik]

fld qword [const_mianownik]
fstp qword [mianownik]

.loop:
finit ; inicjalizacja stosu FPU

fld qword [licznik]         ;licznik na stos
fld qword [mianownik]       ;mianownik na stos
fdiv                        ;wynik dzielenia st1/st0
fadd qword [wynik]          ;st0 = wynik dzielenia + [wynik]

fstp qword [wynik]          ;wywalamy z st0 do [wynik]

                            ;zmieniamy mianownik + 2
fld qword [mianownik]       ;mianownik na stos
fadd qword [zwiekszmian]    ;st0 = mianownik + 2
fstp qword [mianownik]          ;wywalamy z st0 do [mianownik]

                            ;zmieniamy licznik *(-1)
fld qword [licznik]         ;licznik na stos
fchs                        ;st0 = -st0 = -licznik
fstp qword [licznik]        ;wywalamy z st0 do [licznik]

                        ;sprawdzanie dokladnosci
fld qword[wynik]        ;wynik na stos
fldpi                   ;pi na stos
fsub                    ;st0 = wynik-pi = st1 - st0
fabs                    ;st0 = |wynik-pi|

fld qword a             ;st0 = zadana dokladnosc

                            ;(Unordered Compare ST(0) to ST(i) and set CPU flags and Pop ST(0))
                            ;Przyrostek p oznacza obniżenie stosu rejestrów koprocesora, przyrostek i oznacza zapisywanie wyników bezpośrednio do flag procesora a nie flag koprocesora
fucomip st0, st1            ;porownanie z dokladnoscia  if(zadana dokladnosc > uzyskana)


jb    .loop   ;only the C0 bit (CF flag) would be set if no error


fld qword [wynik]

        ;zwraca to co w st0
leave   ; LEAVE = mov esp, ebp / pop ebp
ret


section .data:

wynik       dq 4.0
licznik     dq -4.0
mianownik   dq 3.0
zwiekszmian dq 2.0

const_wynik     dq 4.0
const_licznik   dq -4.0
const_mianownik dq 3.0
nasm -o pi.o -f coff pi.asm
gcc pi.o pi_interface.c -o projekt.exe -Wall -Wextra