cout 未能提供输出可能是由于内联汇编

Posted

技术标签:

【中文标题】cout 未能提供输出可能是由于内联汇编【英文标题】:cout fails to give output probably due to inline assembly 【发布时间】:2020-02-03 21:45:53 【问题描述】:

我正在使用 Visual Studio 2019 开发人员命令提示符。内联汇编代码是简单的除法和余数。使用命令cl /EHsc filename.cpp编译没有错误。屏幕上绝对没有显示任何内容。它最多需要 4 秒的运行时间。

#include<iostream>
using namespace std;
int main()

    int x=10,y=20;
    int z=0,r=0;
    //z=x/y
    //r=x%y
    __asm
    
        MOV EAX,x
        IDIV y
        MOV z,EAX
        MOV r,EDX
    
    cout<<"z = "<<z<<"\tr = "<<r<<endl;
    return 0;

【问题讨论】:

我在这段代码中看不到任何会干扰cout 的内容。您只需要使用调试器跟踪代码即可。但是你为什么要使用内联汇编,而不是简单地在普通 C++ 代码中使用 /% 运算符?让编译器根据需要为您优化。 如果您想提高效率,请使用std::div 1.使用调试器。 2. 忘记内联汇编 3. 忘记汇编 @MichaelChourdakis "忘记组装" 如果您想成为一名工程师,开发驱动程序或接近嵌入式硬件上的骨协议,该怎么办。或者,如果您想在操作系统内核上进行开发。或者如果你想编写编译器?或者如果你想在 HPC 上工作?或者只是为了更好地理解幕后发生的事情以编写更好的抽象?或者如果你想写一门新的编程语言怎么办? @G.Sliepen:这是 MSVC,而不是 GNU C 内联汇编。 MSVC 解析你的 asm 并找出你触摸了哪些寄存器。 【参考方案1】:

您在MOV EAX,xIDIV y 指令之间缺少CDQ。没有它,EDX 寄存器中有一个未知值,可能导致除法溢出。 CDQ 指令会将EAX 签名扩展为EDX

MOV EAX,x
CDQ
IDIV y

【讨论】:

@MohammadShahwez:还值得一提的是,这个内联汇编完全没有意义;编译器将为您执行此优化(使用一个idiv 的两个输出),或者甚至不使用idiv 作为编译时间常数除数更好。 (即使使用运行时变量除数。)使用 MSVC 内联 asm 引入了两个输出的存储/重新加载。见What is the difference between 'asm', '__asm' and '__asm__'? @MohammadShahwez:另外值得一提的是:在更好的操作系统下,您会看到程序因除法异常而崩溃。例如在 Linux 等类 Unix 操作系统上,操作系统会以 SIGFPE 算术异常终止您的进程,并且命令行 shell 会报告这一事实。在 Windows 下,也许尝试 Powershell,以防它只是 cmd 不好并且没有报告异常程序终止。

以上是关于cout 未能提供输出可能是由于内联汇编的主要内容,如果未能解决你的问题,请参考以下文章

GCC内联汇编常见陷阱

使用 gcc 编译内联汇编时出错,“shl”

扩展内联汇编:输入和输出的相同变量

输出是不是总是由 C 中的内联汇编中的 %eax 寄存器确定?

扩展内联汇编基础

内联汇编约束修饰符 = 和 +