- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
此程序必须根据用户提供的精度计算圆周率。calculate_pi()函数是用NASM写的。有人可以向我解释为什么如果评论此行:
//printf("accuracy: %.15f\n", precision); //<- This line
程序无法正常运行。向 calcuta_pi() 函数发送奇怪的数字?如果注释掉这一行,就会向函数发送一个非常小的值,程序将无限运行。
但如果不是注释程序,则它可以正常工作。
#include <stdio.h>
#include <math.h>
extern double calculate_pi(double precision); /* external function declaration */
double calculate_pi(double precision); /* function prototype */
int main()
{
double precision = 1;
printf("A program that calculates pi, with accuracy provided by the user\n");
printf("Give me accuracy\n");
while(1)
{
if (scanf("%lf", &precision) != 1)
{
printf("reading error\n");
fseek(stdin,0,SEEK_END);
continue;
}
if(precision<0)
precision = fabs(precision);
//printf("accuracy: %.15f\n", precision); //<- This line
printf("pi: %.15f\n", calculate_pi(precision));
}
return 0;
}
这是我的汇编代码:
; 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
最佳答案
我认为您错误地访问了函数 arg,偏移了 4 个字节。当你制作堆栈框架时,第一个 arg 位于 [ebp+8]
,但你正在从 [ebp+12]
加载. (这适用于在堆栈上传递参数的所有调用约定。我认为 32 位 mingw 默认情况下为 double
执行此操作。)
这意味着您用作 precision
的 double
值的高 4 字节来自调用者碰巧留在 8 字节 arg 槽上方的堆栈中的任何内容.这解释了为什么调用者的变化会影响你的函数的行为,以及为什么你会得到一个无限循环:如果你加载的字节恰好代表一个非常小的 double
,你的循环永远不会退出。
低 4 个字节(尾数的 32 个最低有效位)来自调用者传递的前 4 个字节。
通过查看寄存器并注意到您加载的值不是调用者传递的值,您可以使用调试器轻松找到它。此外,@Ped7g 的建议只是尝试在一个普通的 asm 函数中返回 precision
也会发现问题。
关于windows - 在调用 asm 函数之前在 C 中调用 printf 或不调用的神秘副作用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47845728/
我需要处理来自旧 Mac 时代(旧摩托罗拉 CPU)的文件。字节是大端字节序,所以我有一个函数可以将 Int64 交换为英特尔小端字节序。该函数是 ASM,可在 32 位 CPU 上运行,但不能在 6
1.概述 转载:史上最通俗易懂的ASM教程 一勺思想 We are all in the gutter, but some of us are looking at the stars. (我们都生活
1.概述 转载:ASM 与 Presto 动态代码生成简介 代码生成是很多计算引擎中常用的执行优化技术,比如我们熟悉的 Apache Spark 和 Presto 在表达式等地方就使用到代码生成技术。
我想在 C++ 程序中使用 ASM 调用地址为 774a7fdch 的函数(kernel32.dll 函数) 我正在使用 Visual Studio 2010。 我该怎么做? call 774a7fd
我是否正确转换了它? 原始 VS C++ 版本: _TEB *pTeb = NULL; _asm { mov eax, fs:[0x18];
阅读自howto_add_systemcall "In general, header files for machine architecture independent system calls
在实现无锁数据结构和时序代码时,通常需要抑制编译器的优化。通常人们使用 asm volatile 和 clobber 列表中的 memory 来执行此操作,但有时您只会看到 asm volatile
这个“strcpy”函数的目的是将src的内容复制到dest,结果很好:显示两行“Hello_src”。 #include static inline char * strcpy(char * de
我正在尝试进行一些汇编编码,我从 C 语言调用函数。代码本身运行良好,但我有两个巨大的问题在很长一段时间内无法解决。第一个是语法高亮 - 我安装了两个不同的(当时一个)asm 高亮扩展到 Visual
我正在研究一些类文件分析,并且正在研究使用 ASM 来读取类。在 Javap 中,操作码以及 tagName 和 tagValue 是内联打印的,但在每个 AbstractInsnNode 中,我只看
我正在尝试弄清楚如何将 ASM 中的 DB 变量用于内联 ASM C++ 我有这个 ASM 代码: filename db "C:\imagen.bmp" eti0: mov ah,3dh mov a
这个“strcpy”函数的目的是将src的内容复制到dest,结果很好:显示两行“Hello_src”。 #include static inline char * strcpy(char * de
在 mm/memory.c 中,它包含一个文件: #include tlb.h 是 include/asm-generic/tlb.h或 arch/arm/include/asm/tlb.h ? 最
你好我找到了一个asm代码......它被集成到c++项目中 template T returned; BYTE *tem = buffer; __asm { mov eax, tem
问题:当我运行 @ 命令提示符 >tasm HelloWorld.asm 顺便说一句,我在输入文件名 HelloWorld.asm 时使用 TAB,所以没有错字.我收到这个致命的命令行错误: Turb
尝试通过 eax 从 asm proc 返回一个 long int,后来又尝试通过 dx:ax。两者都不适合我,因为 C printf 打印的数字与所需的 320L 不同。 x.asm: .model
这是 godbolt 生成的代码. 下面是 Visual Studio 在我的 main.asm 文件上生成的相同代码(通过 Project->C/C++->Output Files->Assembl
在构建具有依赖项的 giraph jar 时,我们收到以下警告.. 真的不知道如何解决这些.. 我们已经尝试过了 useProjectArtifact 为 false 和 解压为真 两者似乎都有效 任
我正在使用 gentoo 并尝试编译一个程序来控制并行端口上的位。它的顶部附近有这条线: #include 当我尝试在其上使用 gcc 时,它会产生以下输出: port.c:4:20: error:
(原帖)将 hibernate 依赖项添加到 pom.xml 时显示错误 2011-10-11 10:36:53.710::WARN: failed guiceFilter java.lang.No
我是一名优秀的程序员,十分优秀!