【发布时间】:2016-03-28 16:16:40
【问题描述】:
我正在尝试编写一个即时编译器,但我有一段不想工作的代码。我的平台是 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();
我认为 C++ 部分很好,因为我已经用简单的算术运算尝试过它并且效果很好。
所以无论如何都没有分段错误,代码似乎已执行但没有任何反应,stdout 中没有任何内容。
有什么建议吗?
//编辑:完整的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;
};
【问题讨论】:
-
不确定,但有可能被缓冲了吗?
-
另外,
int 0x80是否支持 64 位? -
@MatsPetersson 我认为支持
int 0x80:en.wikibooks.org/wiki/X86_Assembly/Interfacing_with_Linux 我也尝试过syscall,结果相同。不知道你说的缓冲是什么意思?纯汇编不是无缓冲的吗? -
在将输出发送到标准输出之前,是否有一个中间阶段可以保留您的输出?
-
@simplicisveritatis 我不确定,我对这些东西真的很陌生。 :) 我添加了完整的 C++ 代码。
标签: c++ assembly stdout machine-code yasm