我正在尝试解析IL,以发出一种方法。我已经在string []中获得了方法的IL代码,其中每个字符串都是IL指令。我遍历此数组并使用ILGenerator添加OpCodes:
foreach (string ins in instructions) //string representations of IL
{
string opCode = ins.Split(':').ElementAt(1);
// other conditions omitted
if (opCode.Contains("br.s"))
{
Label targetInstruction = ilGenerator.DefineLabel();
ilGenerator.MarkLabel(targetInstruction);
ilGenerator.Emit(OpCodes.Br_S, targetInstruction);
}
Run Code Online (Sandbox Code Playgroud)
这是我需要重现的IL:
Source IL:
IL_0000: nop
IL_0001: ldstr "Hello, World!"
IL_0006: stloc.0
IL_0007: br.s IL_0009
IL_0009: ldloc.0
IL_000a: ret
Run Code Online (Sandbox Code Playgroud)
这是我得到的输出:
Target IL:
IL_0000: nop
IL_0001: ldstr "Hello, World!"
IL_0006: stloc.0
IL_0007: br.s IL_0007 // this is wrong -- needs to point to IL_0009
IL_0009: ldloc.0
IL_000a: ret
Run Code Online (Sandbox Code Playgroud)
如您所见,br.s调用指向自身,这当然会导致无限循环。如何获得源代码中的以下说明?这与使用Reflection.Emit.Label有关,但是我不确定它是如何工作的。
编辑通过上面看到的IL就是这种简单方法, …
在解码 x87 FPU 指令方面,我面临着一个模棱两可的情况。看看下面的指令取自第 2A 卷英特尔指令集手册 [1] 的第 3-380 页。
D9 /0 --> FLD m32fp --> Push m32fp onto the FPU register stack.
D9 C0+i --> FLD ST(i) --> Push ST(i) onto the FPU register stack.
Run Code Online (Sandbox Code Playgroud)
这两条指令都具有相同的单字节基本操作码0xD9。第一条指令的扩展操作码为0x00. 扩展操作码将在 ModR/M 字节的“reg”字段中指定。但第二条指令是一个 2 字节的操作码,具有“添加到获取寄存器”功能。这意味着:
D9 C0 --> FLD ST0
D9 C1 --> FLD ST1
(and so on)
Run Code Online (Sandbox Code Playgroud)
关于区分这两个指令,我有一个小问题。一个小例子是:
现在,假设我得到操作码序列"D9 C1"。如果我需要检查它是否是指令"FLD m32fp",那么我必须检查 ModR/M 字节的“reg”字段是否为 0x00。如果是这样,那么它确实是"FLD m32fp"正在使用的指令。
的二进制表示C1是"1100 0001"。假设bit0是LSB,那么bit3-bit5(含)构成ModR/M字节的'reg'字段"C1" …
我在代码的各个地方都看过这个术语,比如图形编程样本.它似乎是一个C++语义,但显然有一个名为EmitCalli的C#/ .NET托管实现似乎与OpCodes.Calli有关.我认为这是一种机器语言指令.这个术语的解释是否与外行人的术语有些接近?
我正在阅读Richard C. Detmer 撰写的题为"80x86汇编语言和计算机体系结构简介"的教科书
我有一个关于即时内存mov操作码的问题.这里也是我所指的文字部分:
继续下图4.1,下一行是即时到内存的移动.这些指令中的每一个都有操作码
C6,ModR/M字节,附加地址字节(如果需要),最后是包含立即操作数的字节.如上所述对地址进行编码以用于存储器到寄存器移动.例如,如果smallCounter引用内存中的一个字节并mov smallCounter, 100组装指令,则汇编器将生成7(3 + 4)个字节的目标代码C6 05 xx xx xx xx 64,其中xx xx xx xx表示内存中的地址,64表示字节大小的十六进制版本100 .00 000 101对于直接存储器寻址,ModR/M字节05是Mod = 00和R/M = 101,不需要Reg字段并设置为000.作为另一个示例,考虑
mov BYTE PTR [edx], -1使用寄存器间接模式的存储器目的地.操作码仍然是C6,而立即字节(总是最后一个)现在是FF为-1.第二个字节是ModR/M字节,其中Mod = 00用于寄存器间接,Reg = 000(未使用),R/M = 010用于EDX,制作00 000 010或02.目标代码用于C6 02 FF.第92页,第4章,第1节 - 复制数据
图4.1 - 带有字节目标的mov指令 - 是一个包含四列的图表:
上述部分中图中的线也是: …
我正在用C编写我的第一个NES模拟器.目标是使其易于理解并且周期准确(尽管不一定必须具有代码效率),以便以正常的"硬件"速度玩游戏.当深入研究6502的技术参考时,似乎指令消耗了多个CPU周期 - 并且根据给定条件(例如分支)也有不同的周期.我的计划是创建读写函数,并通过使用a来寻址模式来对操作码进行分组switch.
问题是:当我有一个多周期指令,例如a时BRK,我是否需要模拟每个周期中发生的事情:
#Method 1
cycle - action
1 - read BRK opcode
2 - read padding byte (ignored)
3 - store high byte of PC
4 - store low byte of PC
5 - store status flags with B flag set
6 - low byte of target address
7 - high byte of target address
Run Code Online (Sandbox Code Playgroud)
...或者我可以在一个'周期'(一个switch case)中执行所有必需的操作,而在剩余的周期中什么都不做?
#Method 2
1 - read BRK opcode,
read padding byte (ignored),
store high byte of …Run Code Online (Sandbox Code Playgroud) 在英特尔软件开发人员手册中,第2A章2.1.2节说明了这一点
用于通用和SIMD指令的双字节操作码格式包括以下之一:
- 转义操作码字节0FH作为主操作码和第二操作码字节.
- 强制前缀(66H,F2H或F3H),转义操作码字节和第二个操作码字节(与前一个子弹相同).
什么是'逃避操作码',它的目的是什么?
我正在编写一个 x86-64 汇编程序。我正在浏览 Intel x86 手册第 2 卷,试图了解如何从程序集中生成正确的指令。我主要了解它是如何工作的,但一直在组装和拆卸说明以检查我是否正确。
在 ADD 参考表(第 2A 卷,3.31)中:
opcode | Instruction
04 ib | ADD AL, imm8
05 iw | ADD AX, imm16
05 id | ADD EAX, imm32
REX.W + 05 id | ADD RAX, imm32
Run Code Online (Sandbox Code Playgroud)
集合:
;add.s
add al, 1
add ax, 1
add eax, 1
add rax, 1
Run Code Online (Sandbox Code Playgroud)
拆卸:
.text:
0: 04 01 add al, 1
2: 66 83 c0 01 add ax, 1
6: 83 c0 01 add eax, 1
9: …Run Code Online (Sandbox Code Playgroud) 这些是MOV来自Intel\xc2\xae 64 和 IA-32 架构软件开发人员手册的指令操作码:
B8+ rd id MOV r32, imm32 OI Valid Valid Move imm32 to r32。
C7 /0 id MOV r/m32, imm32 MI Valid Valid Move imm32 to r/m32。
我拆解如下:
\n0: b8 44 33 22 11 mov eax, 0x11223344\nRun Code Online (Sandbox Code Playgroud)\n0: 67 c7 00 44 33 22 11 mov DWORD PTR[eax], 0x11223344\nRun Code Online (Sandbox Code Playgroud)\n我想问的问题是:
\n为什么C7操作码是寄存器/内存(r/m32, imm32)而不是仅内存(m32, imm32)?
是否有任何时候我们使用 …
哪种结构更快:
$a = $b * $c ? $b * $c : 0;
Run Code Online (Sandbox Code Playgroud)
要么
$i = $b * $c;
$a = $i ? $i : 0;
Run Code Online (Sandbox Code Playgroud)
所有变量都是本地变量.
对于多重复制,添加,减法和除法,速度是否不同?
这里有一些澄清:
BoltClock为我提供了有用的信息,但user576875通过发布操作码解码器的链接来完成我的一天!他的答案也包含对我问题的直接回答.谢谢!
在检查由PHP脚本生成的操作码时,我感到很惊讶,与其他字符串函数(例如)不同str_pad(),strlen()它不是像以前那样的函数调用(如果我没记错的话),但是有专用的STRLEN操作码:
strlen($c);
str_pad($c, 2);
Run Code Online (Sandbox Code Playgroud)
...
8 4 STRLEN ~7 !2
...
9 6 INIT_FCALL 'str_pad'
7 SEND_VAR !2
8 SEND_VAL 2
9 DO_ICALL
Run Code Online (Sandbox Code Playgroud)
https://3v4l.org/9QJQ7/vld#output
此操作码是在哪个PHP版本中引入的?我在任何地方都找不到此信息。