Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/130.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ YASM程序集在jitted函数中调用stdout.write_C++_Assembly_Stdout_Machine Code_Yasm - Fatal编程技术网

C++ YASM程序集在jitted函数中调用stdout.write

C++ YASM程序集在jitted函数中调用stdout.write,c++,assembly,stdout,machine-code,yasm,C++,Assembly,Stdout,Machine Code,Yasm,我正在尝试编写一个即时编译器,我有一段代码不想工作。我的平台是x86-64 ubuntu 我用yasm编写了以下代码: bits 64 mov rdx, 1 mov rcx, 'A' mov rbx, 1 mov rax, 4 int 0x80 ret 因此,如果我理解正确,应该将A写入标准输出。现在我用 yasm -f bin test.yasm 这导致以下机器代码: 0x48 0xc7 0xc2 0x01 0x00 0x00 0x00 0x48 0xc7 0xc1 0x41 0x00

我正在尝试编写一个即时编译器,我有一段代码不想工作。我的平台是x86-64 ubuntu

我用yasm编写了以下代码:

bits 64

mov rdx, 1
mov rcx, 'A'
mov rbx, 1
mov rax, 4
int 0x80
ret
因此,如果我理解正确,应该将
A
写入标准输出。现在我用

yasm -f bin test.yasm
这导致以下机器代码:

0x48 0xc7 0xc2 0x01 0x00 0x00 0x00 0x48 0xc7 0xc1 0x41 0x00
0x00 0x00 0x48 0xc7 0xc3 0x01 0x00 0x00 0x00 0x48 0xc7 0xc0
0x04 0x00 0x00 0x00 0xcd 0x80 0xc3

然后我在C++中读取结果代码并称之为:

void *memory = allocate_executable_memory(sizeof(code));
emit_code_into_memory(sizeof(code), code, memory);
JittedFunc func = reinterpret_cast<JittedFunc>(memory);
func();
void*memory=分配可执行内存(sizeof(code));
将代码发送到内存中(sizeof(code),code,memory);
JittedFunc func=重新解释强制转换(内存);
func();

我认为C++部分是好的,因为我已经尝试过简单的算术运算,而且它工作得很好。 所以不管怎么说,没有分段错误,代码似乎被执行了,但什么也没发生,标准输出中什么都没有

有什么建议吗

<强> //Ed:<强>完全C++代码:

#include <stdio.h>
#include <string.h>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <sys/mman.h>

void* allocate_executable_memory(size_t size) {
    void *ptr = mmap(
        0,
        size,
        PROT_READ | PROT_WRITE | PROT_EXEC,
        MAP_PRIVATE | MAP_ANONYMOUS,
        -1,
        0
    );
    if (ptr == (void*)(-1)) {
        perror("mmap");
        return nullptr;
    }
    return ptr;
};

void emit_code_into_memory(size_t code_length, uint8_t *code, void *memory) {
    memcpy(reinterpret_cast<uint8_t*>(memory), code, code_length);
};

typedef void (*JittedFunc)();

int main(int argc, char* argv[]) {
    /* Use like this:
    bin/jit 0xb8 0x11 0x00 0x00 0x00 0xc3
    */
    if (argc <= 1) {
        return 1;
    }

    uint8_t code[argc-1];
    for (int i = 1; i < argc; i++) {
        code[i-1] = std::stoul(argv[i], nullptr, 16);
    }

    void *memory = allocate_executable_memory(sizeof(code));
    emit_code_into_memory(sizeof(code), code, memory);
    JittedFunc func = reinterpret_cast<JittedFunc>(memory);
    func();
    return 0;
};
#包括
#包括
#包括
#包括
#包括
#包括
void*分配可执行内存(大小){
void*ptr=mmap(
0,
大小,
PROT|u READ | PROT|u WRITE | PROT|u EXEC,
MAP|u PRIVATE | MAP|u ANONYMOUS,
-1,
0
);
如果(ptr==(void*)(-1)){
佩罗尔(“mmap”);
返回空ptr;
}
返回ptr;
};
void将代码释放到内存中(大小代码长度,uint8代码,void*内存){
memcpy(重新解释转换(内存)、代码、代码长度);
};
typedef void(*JittedFunc)();
int main(int argc,char*argv[]){
/*这样使用:
bin/jit 0xb8 0x11 0x00 0x00 0x00 0xc3
*/

如果(argcwrite系统调用需要指向要写入的对象的指针,而不是立即数。此外,64位使用具有不同调用约定的
syscall
指令。这对于指针非常重要,否则指针将被截断为32位。此外,函数号也不同,因此您的代码实际调用
stat
syscall,可以使用
strace

stat(NULL,NULL)=-1默认值(错误地址)
您应该尝试以下代码:

push 'A'
mov rdi, 1   ; stdout
mov rsi, rsp ; buf
mov rdx, 1   ; count
mov rax, 1   ; sys_write
syscall
pop rdi      ; cleanup
ret
这使用堆栈来存储要打印的信件。清理可以使用任何调用方保存的暂存寄存器,也可以重写为
add rsp,8
。系统调用的返回值位于
eax

32位版本可能如下所示:

push ebx;被调用方已保存
推‘A’
mov ebx,1;标准输出
mov-ecx,尤指;buf
mov edx,1;计数
mov eax,4;系统写入
int 0x80
pop edi;清除buf
弹出ebx;恢复ebx
ret

请注意,
ebx
必须根据调用约定进行保存。

不确定,但它是否有缓冲的可能?另外,
int 0x80
是否支持64位?@matstpeterson我认为
int 0x80
是受支持的:我也尝试了
syscall
,结果相同。我不确定你所说的缓冲是什么意思?不是纯asm无缓冲?是否有中间阶段可能在将输出发送到标准输出之前保留输出?@simplicisveritatis我不确定,我对这种东西真的很陌生。:)我已经添加了完全的C++代码。这是非常好的。我们如何在32位计算机上使用<代码> int 0x80/CODE >这样做,而不是传递一个即时值,而是将它推到堆栈上,然后传递堆栈指针,对吗?为什么有一个特殊的原因,为什么你要弹出<代码> RDI < /代码>进行清理?r的责任在这里。@DavidHoelzer是的,我知道他为什么突然出现,但为什么要
rdi