【发布时间】:2016-06-01 13:37:00
【问题描述】:
我正在尝试编写自己的 I/O 库,所以第一步就是能够输出一个字符。到目前为止,这只需要在 Linux 上工作。我在 x86(使用 Intel 语法)中编写了我认为是可靠的_putc: 标签,并将它放在“io.h”中,然后从我的主文件“test.cpp”中调用它。下面是 test.cpp 的内容:
#include "io.h"
extern void _putc(char) __asm__("_putc");
int main(int argc, char** argv){
_putc('c');
return 0;
}
这是我的 io.h:
asm(
"\n.intel_syntax noprefix"
"\n.globl _putc"
"\n_putc:"
"\n\tpush [ebp]"
"\n\tmov ebp,esp"
"\n\tmov eax,4"
"\n\tmov ebx,0"
"\n\tmov ecx,[ebp+8]"
"\n\tmov edx,1"
"\n\tint 0x80"
"\n\tret"
"\n.att_syntax" ;return to g++'s at&t syntax
);
我正在使用 G++
在 x86_64 Linux 操作系统上开发它我用这个来编译:
g++ -o test test.cpp -Wall
运行时会立即出现段错误。我认为我的问题是调用约定,但没有办法绝对确定。我尝试将程序集包装在一个函数 (void _putc(char c)) 中并删除全局标签,但这没有帮助。我还尝试推送 ebp 的内容而不是它指向的内容,但它无法编译。
注意:这只能与主文件中的行 #include io.h 一起工作(我可以在此工作后移动 extern void _putc(char) __asm__("_putc");),并且它必须与 C++ 一起工作,而不仅仅是C。另外,请不要跟我讲头文件中的函数定义,这正是我正在做的。
【问题讨论】:
-
有一种方法可以绝对确定:使用调试器。
-
我做到了。它在
push [ebp]出现段错误。 -
这是一个好点,但它一开始就出现了段错误,没有处理中断。所以肯定还有另一个问题。另外,我不知道什么是“clobbering”或者如何告诉汇编程序我正在这样做,你能解释一下吗?
-
当然
push [ebp]获取ebp指向的内存地址的值并将其推送。但是,我认为您的意思是用push ebp推动ebp的值。如果您在push ebp上遇到错误,那么我怀疑您是编译为 64 位还是 32 位代码? -
这样的事情也是等待 GCC 内联汇编器发生的灾难:
mov ecx,[ebp+8]。您假设putc的参数位于堆栈上的特定位置。但是,如果您的代码得到优化,那么您感兴趣的值很可能被放入寄存器中。
标签: c++ linux g++ x86-64 inline-assembly