从C++调用程序集代码
Calling Assembly code from C++
我正在尝试编写自己的I/O库,所以第一步就是能够输出一个字符。到目前为止,这只需要在Linux上工作。我用x86(使用英特尔语法)编写了我认为是可靠的_putc:
标签,并将其放在"io.h"中,然后从我的主文件"test.cpp"中调用它。以下是测试的内容.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:"
"ntpush [ebp]"
"ntmov ebp,esp"
"ntmov eax,4"
"ntmov ebx,0"
"ntmov ecx,[ebp+8]"
"ntmov edx,1"
"ntint 0x80"
"ntret"
"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。另外,请不要在头文件中教我函数定义,这就是我正在做的事情。
对于 64 位代码,您确实需要考虑使用 syscall
而不是 int 0x80
。系统调用使用 64 位约定,系统调用号码与 32 位代码中的int 0x80
不同。您可以了解此表中的 64 位系统调用。sys_write
和sys_read
调用如下所示:
%rax System call %rdi %rsi %rdx %r10 %r8 %r9 0 sys_read unsigned int fd char *buf size_t count 1 sys_write unsigned int fd const char *buf size_t count
如果您想了解如何在 64 位 Linux 代码中传递参数,则需要熟悉 System V 64-Linux ABI。在输入调用后,如果您打算调用其他函数或系统调用,通常必须将堆栈与 16 字节边界对齐。
您的代码还存在一个缺陷,即将字符传递给sys_write
。 sys_write
需要一个包含字符的缓冲区的地址,而不是字符本身。
这是一个可以工作的代码转储:
asm(
"n.intel_syntax noprefix"
"n.globl _putc"
"n_putc:"
"ntadd rsp, -8" // Allocate space on the stack to store the character passed
// Also aligns stack back to 16-bye boundary
// with return address already on stack
"ntmov [rsp],rdi" // Move the character passed in RDI to memory(stack) for sys_write
"ntmov eax,1" // With 64-bit syscalls RAX = 1 for sys_write
"ntxor edi,edi" // 1st parameter to syscall is in RDX. FD = 0
"ntlea rsi,[rsp]" // We need to pass pointer to memory containing our char
"ntmov edx,1" // RDX = 1 character to print. Could reuse EAX instead of 1 for src
"ntsyscall" // Make syscall (using syscall instead of int 0x80 for 64-bit)
"ntadd rsp, 8" // Restore stack to state right after function entry
"ntret"
"n.att_syntax prefix" //return to g++'s at&t syntax
);
- 用于将C++代码转换为 Web 程序集的脚本未终止
- 为什么我的C++程序的程序集输出充满了 .ascii,没有汇编代码?
- 为什么在堆栈和堆上创建变量会产生相同的程序集代码?
- 为什么从 constexpr 引用生成的程序集代码与从 constexpr 指针生成的程序集代码不同?
- 在OpenGL中使用程序集代码渲染视频时出错
- 如何编写与此程序集代码相等的c/c++代码
- 在链接的程序集文件中,我想从 c++ 调用代码访问变量.是否可以在不触发访问冲突的情况下执行此操作?
- 在 C++ 中调用时对内联程序集代码的未定义引用
- 将程序集 NASM 代码链接到 GCC
- 确定代码中当前程序集是否为 32/64 位的最简单方法
- 在结构中嵌入函数程序集代码
- 程序集字符串和 C++ 中的等效代码
- 为什么添加内联程序集注释会导致 GCC 生成的代码发生如此根本的变化?
- 使用 Visual Studio 从C++代码调用程序集过程
- 如何使用g++获取C++头文件(.hpp)的程序集代码
- 从我的 C/C++ 代码 - x86 和 ARM 获取程序集等效代码
- 如何将此c++代码转换为程序集
- C++外部程序集:我的代码中的错误在哪里
- 如何在不创建新进程的情况下运行程序集代码
- 从C++调用程序集代码