gpt4 book ai didi

perl - 如何处理存储在 Perl 二进制文件中的操作码?

转载 作者:行者123 更新时间:2023-12-04 06:07:10 25 4
gpt4 key购买 nike

Creating Your Own Abstract Processor是关于我正在尝试做的事情的快速论文。

http://malcon.org/ctm.rar是关于模拟器应该是什么的确切规范。

我正在用 Perl 编写一种模拟器。该程序将读入一个二进制文件并将二进制文件的十六进制处理为 Action ,处理器如何工作,但基于不同操作码的软件。只是一个挑战的事情。

无论如何,我不完全确定如何将二进制文件读入数组,然后将数组中的十六进制分配给操作码。这是我的代码的一部分:

my $opcode='';
my $file= "path/to/file";
my $IP=0;
my $SP=0;
my $FLAG=0;
my $A=0;
my $B=0;
my $X=0;
my @STACK=(0);

open(F, "<".$file) || die("Could not open file");
binmode(F);
my @ROM = <F>;
close(F);

while($IP >= 0)
{
$opcode="$ROM[$IP]";
if ($opcode eq 11) {
$A = $STACK[$SP];
$IP++;
}
if ($opcode eq 12) {
$B = $STACK[$SP];
$IP++;
}
if ($opcode eq 13) {
$A = $B;
$IP++;
}
if ($opcode eq 14) {
$B = $A;
$IP++;
}

这只是我需要帮助的代码的一部分。如果您出于某种原因需要查看更多内容,请告诉我。

所以我改变了我的代码以反射(reflect)上面的答案,我的代码现在看起来像这样:
my $opcode='';
my $file= "CTM-bootrom";
my $IP=0;
my $SP=0;
my $FLAG=0;
my $A=0;
my $B=0;
my $X=0;
my @STACK=(0);

open my $ROM, '<:raw', $file or die "Cannot open '$file': $!";

{
local $/ = \1; # Read one byte at a time
while (my $byte = <$ROM>){
while($IP >= 0)
{
$opcode=$ROM[$IP];
if ($opcode eq 11) {
$A = $STACK[$SP];
$IP++;
}
if ($opcode eq 12) {
$B = $STACK[$SP];
$IP++;
}
if ($opcode eq 13) {
$A = $B;
$IP++;
}

但现在我收到一个错误:

Use of uninitialized value $opcode in string eq at Aod8.pl line 73,



<$ROM> 对我来说似乎操作码已初始化...我该如何解决这个问题?

最佳答案

我不一定认为一次读取二进制一个字符是个好主意(尽管对于足够小的文件,您大部分时间都会从缓冲区中获取)。从概念上讲,将文件读入平面数组会更好。你可以通过使用

my @ROM = do {
local $/ = \1;
map ord, <$fh>;
};

我认为这回答了你的问题的要点。

现在,对于不将整个文件读入数组,而是使用文件本身作为可执行镜像的想法,这里是我根据这篇文章的早期版本和反馈编写的一个小脚本。

请注意,整个标量文件句柄是通过复制和粘贴来为运行包含在您链接的文章中的 ROM 提供脚手架,而不必创建二进制文件。
#!/usr/bin/env perl

use strict;
use warnings;

use Fcntl ':seek';
use Try::Tiny;

my %ROMS = (

rom1 => [0x04, 0x41, 0x09, 0x02, 0x0a],

rom2 => [
0x04, 0x41, 0x09, 0x02,
0x07, 0x09, 0x02, 0x07,
0x09, 0x02, 0x07, 0x09,
0x02, 0x07, 0x09, 0x02,
0x0A,
],

rom3 => [
0x04, 69, 0x09, 0x02, 0x04, 110, 0x09, 0x02,
0x04, 116, 0x09, 0x02, 0x04, 101, 0x09, 0x02,
0x04, 114, 0x09, 0x02, 0x04, 32, 0x09, 0x02,
0x04, 97, 0x09, 0x02, 0x04, 32, 0x09, 0x02,
0x04, 67, 0x09, 0x02, 0x04, 104, 0x09, 0x02,
0x04, 97, 0x09, 0x02, 0x04, 114, 0x09, 0x02,
0x04, 32, 0x09, 0x02, 0x04, 58, 0x09, 0x02,
0x04, 32, 0x09, 0x02, 0x04, 50, 0x03, 0x01,
0x04, 2, 0x03, 0x04, 89, 0x09, 0x02, 0x04,
111, 0x09, 0x02, 0x04, 117, 0x09, 0x02, 0x04,
32, 0x09, 0x02, 0x04, 84, 0x09, 0x02, 0x04,
121, 0x09, 0x02, 0x04, 112, 0x09, 0x02, 0x04,
101, 0x09, 0x02, 0x04, 100, 0x09, 0x02, 0x04,
32, 0x09, 0x02, 0x04, 58, 0x09, 0x02, 0x04,
32, 0x09, 0x02, 0x04, 50, 0x03, 0x02, 0x0A,
]

);

for my $rom (sort keys %ROMS) {
my $rom_s = join '', map chr, @{ $ROMS{ $rom } };

open my $rom_h, '<:raw', \$rom_s
or die "Cannot open handle to ROM string: $!\n";

print "Executing $rom\n";

try {
execute($rom_h);
}
catch {
print "\n$rom: $_\n";
};

close $rom_h
or die "Cannot close handle to ROM string: $!\n";
}

sub get_next_byte {
my ($fh) = @_;
my $byte = do {
local $/ = \1;
scalar <$fh>;
};

return unless defined $byte;

$byte = ord $byte;

return $byte;
}

sub execute {
my ($ROM) = @_;

my $FLAG = 0;
my $SP = 0;
my $X = 0;
my @STACK;

my @machine = (

# NOP
sub {},

# INPUT
sub { $STACK[$SP] = ord(getc STDIN) },

# OUTPUT
sub { printf STDOUT '%c', $STACK[$SP] },

# MOV SP, X
sub { $SP = $X },

# MOV X, DATA
sub {
$X = get_next_byte($ROM);
},

# CMP X, DATA
sub {
$FLAG = $X - get_next_byte($ROM);
},

# JE
sub {
my $offset = get_next_byte($ROM);

if ($FLAG == 0) {
seek $ROM, $offset, SEEK_CUR
}
},

# INC X
sub { $X += 1 },

# INC SP
sub { $SP += 1 },

# MOV [SP], X
sub { $STACK[$SP] = $X },

# HALT
sub {
die "HALT\n";
},
);

while (1) {
my $opcode = get_next_byte($ROM);

last unless defined $opcode;

if (($opcode >= 0) and ($opcode < @machine)) {
$machine[ $opcode ]->();
}
else {
die sprintf(
"Invalid opcode '%02x' at offset '%x'\n",
$opcode, $.,
);
}
}
}

输出:

执行 rom1

rom1:暂停

执行 rom2
ABCDE
ROM2:暂停

执行 rom3
输入一个字符:d
你输入:d
rom3:暂停

关于perl - 如何处理存储在 Perl 二进制文件中的操作码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8216724/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com