小编Dan*_*ury的帖子

编译器在设置调用堆栈时生成了意外的"IN AL,DX"(操作码`EC`)

我正在查看一些编译器输出,当调用一个函数时,它通常会开始设置调用堆栈,如下所示:

PUSH EBP
MOV EBP, ESP
PUSH EDI
PUSH ESI
PUSH EBX
Run Code Online (Sandbox Code Playgroud)

因此,我们将调用例程的基指针保存在堆栈中,向上移动我们自己的基指针,然后将几个寄存器的内容存储在堆栈中.然后在例程结束时将它们恢复为原始值,如下所示:

LEA ESP, [EBP-0Ch]
POP EBX
POP ESI
POP EDI
POP EBP
RET
Run Code Online (Sandbox Code Playgroud)

到现在为止还挺好.但是,我注意到在一个例程中,设置调用堆栈的代码看起来有点不同.事实上,它看起来像这样:

IN AL, DX
PUSH EDI
PUSH ESI
PUSH EBX
Run Code Online (Sandbox Code Playgroud)

出于多种原因,这非常令人困惑.首先,方法结束代码与上面引用的另一种方法相同,特别是期望在堆栈上可以获得保存的EBP副本.

另一方面,如果我理解正确,该命令IN AL, DX读入AL寄存器,这与EAX寄存器相同,并且因为它发生了,这里的下一个命令是

XOR EAX, EAX
Run Code Online (Sandbox Code Playgroud)

因为程序想要将它在堆栈上分配的一些东西归零.

问题:我想知道这里到底发生了什么,我不明白.被翻译的机器代码IN AL, DX是单字节EC,而指令对PUSH EBP MOV EBP,ESP将对应于三个字节55 88 EC.反汇编程序是否以某种方式误读了这个?或者是依赖于我不理解的副作用的东西?


如果有人好奇,这个机器代码是由CLR的JIT编译器生成的,我正在用Visual Studio调试器查看它.这是C#中的最小再现:

class C {
  string s = "";
  public void f(string s) {
    this.s = …
Run Code Online (Sandbox Code Playgroud)

x86 assembly

4
推荐指数
1
解决办法
165
查看次数

如何将文本文件编译为 C++ 程序作为常量字符串?

I have a C++ program which I'd like to have output a certain text file at some point. Of course I could have it open, read, and output the text file, but then I have to keep the binary and the text file in sync and located together. I'd rather just compile the file in as a string in some part of my build process.

I've seen things like this done as parts of various IDEs. However I'm building from …

c++ gcc clang

3
推荐指数
1
解决办法
2086
查看次数

有没有一种干净的方法可以将重载集转换为适合与 std::visit 一起使用的访问者?

假设我有一个重载集,如下所示:

class C
{
  public: 

    static void f(const A &);
    static void f(const B &);
};
Run Code Online (Sandbox Code Playgroud)

我想做类似的事情

std::variant<A, B> v;

// ...

std::visit(C::f, v);
Run Code Online (Sandbox Code Playgroud)

但这不能编译。是否有某种方法可以获取重载集并将其视为或将其转换为访问者?

c++ variant c++17

3
推荐指数
1
解决办法
269
查看次数

为什么在编译时不能将值类型的GetType()替换为字符串文字?

编辑:这个问题是基于GetType()返回一个字符串的误解.

我正在努力更好地处理C#的工作原理,所以这个问题更具理论性而非实际性.

据我了解,在值类型上调用GetType需要装箱,然后调用方法.但是由于值类型不能继承,但是类型在编译时是已知的,那么为什么编译器不能简单地用字符串文字替换对GetType()的调用?

或者这是可以完成的事情,但是认为没有必要,因为无论如何都不需要在未装箱的值类型上调用GetType?

c# compiler-optimization

2
推荐指数
1
解决办法
261
查看次数

标签 统计

c++ ×2

assembly ×1

c# ×1

c++17 ×1

clang ×1

compiler-optimization ×1

gcc ×1

variant ×1

x86 ×1