在阅读程序计数器时,我开始知道程序计数器的特殊之处在于无法直接修改其值.
是否有任何间接方式来访问/修改程序计数器的内容?
有没有不使用访问指令指针(RIP)的值的方式call,随后由pop汇编语言?或者是否有可以做到这一点的机器代码操作码?
我一直在谷歌搜索没有明确的结果。
我的问题是机器代码中不能有任何零,否则我会收到 SIGSEGV 错误。这是由于服务器加载代码并从一串字节执行它的方式。近调用在到子例程的距离上为零,因此不能选择使用调用。
我使用的是 64 位 linux,并且有 nasm 和 yasm。
对于上下文,这是从引导加载程序调用的代码,该引导加载程序应引导到主应用程序中。该代码段来自带有参数的函数,该参数uintptr_t address指定了写入主应用程序的地址。我相信sp和pc分别是堆栈指针和程序计数器。
这是代码:
sp = *((void **)address + 0);
pc = *((void **)address + 1);
start_new_application(sp, pc);
Run Code Online (Sandbox Code Playgroud)
这里的完整上下文
然后我走了,打印了地址,sp和pc,发现了以下内容:
address -> 0x08010000
sp ------> 0x20050000
pc ------> 0x080132DD
Run Code Online (Sandbox Code Playgroud)
这让我很困惑。我不确定为什么该sp行中有一个+ 0。该sp行可以改写为:
sp = (void *)address;
Run Code Online (Sandbox Code Playgroud)
并做同样的事情?
我的理解是,该地址已被static_casted为一个double void指针,然后sp被赋予地址的解除引用值(0x08010000),并pc已被赋予地址的解除引用值(0x08010001)。然后,在我的printf语句中,显示的这些值是这些地址的取消引用的值。
我的理解在这里正确吗?
我正在练习根据 Mips 参考表将 Mips 指令(beq $t5,$s0,循环)转换为二进制,并且有一系列指令(PC = PC + 4 + 分支地址)用于计算立即值“I”类型的指令,它一直引用“PC”。
电脑指的是什么?看来我应该寻找“循环”标签存储在内存中的位置:特别是找到该内存地址。
当程序计数器 (PC) 溢出时,RISC-V CPU 上会发生什么?
\n例如,执行 0xFFFF\xe2\x80\x99FFFC 处的(32 位)NOP 后,RV32G IALIGN\xc2\xa0= 32 上会发生什么?或者在 RV32GC 上执行 0xFFFF\xe2\x80\x99FFFE 处的 16 位 NOP 后?这两个问题的最简单答案是 \xe2\x80\x9c 没什么,执行从 0x0000\xe2\x80\x990000\xe2\x80\x9d 开始,但是在 0xFFFF\ 处执行 16 位 NOP 后 RV32GC 上会发生什么xe2\x80\x99FFFC 已被执行?同样的答案意味着指令获取可能需要跨越地址空间的末尾,这在架构上听起来并不令人愉快。(话又说回来,对于 IALIGN\xc2\xa0= 16,指令获取可能必须跨越页面边界,这听起来也不那么令人愉快,而且 IIRC x86 实现已经为部分故障引起了很多欢闹。指令获取。)
\n最好参考规范PDF ,尽管我还没有\xe2\x80\x99t 能够在那里找到任何相关内容。如果做不到这一点,\xe2\x80\x99d 听听实际的硬件实现在这种情况下会做什么会很有趣。
\n处理器中的程序计数器 (PC) 是否有可能溢出,如果有,会发生什么?也就是说,如果它可以容纳 1 个字节,那么当它增加到 255 之后会发生什么?
众所周知,微处理器执行任务的过程只是从存储器一个接一个地执行二进制指令,并且有一个程序计数器保存下一条指令的地址。因此,如果我没有记错的话,这就是处理器执行任务的方式。但是还有另一个名为堆栈指针的指针,它的作用与程序计数器几乎相同。我的问题是为什么我们需要一个堆栈指针来指向内存(堆栈)的地址?有人可以告诉我堆栈指针和程序计数器之间的主要区别吗?
如您所知,当子程序调用时,当前PC(程序计数器)值存储在堆栈中.我想在子程序中修改它,如下所示.我希望使用gcc编译器在Intel Core-i7 3632QM上执行此操作.
void main()
{
foo();
}
void foo()
{
pop return address from stack;
modify return address;
push it to stack;
}
Run Code Online (Sandbox Code Playgroud) 处理器型号 I
? Registers
? PC – Program Counter
? Single data register (accumulator) without name
? We will use symbol A to describe operations on this register
? Stack with an unspecified implementation
? Data specified by name or value
? More realistic model will follow later
Instruction Action Description
---------------------------------------------------------------------
load data A = data Load data to accumulator
store data data = A Store data from accumulator to memory
add data A += data Add data to …Run Code Online (Sandbox Code Playgroud) 我有一个指令块,我想知道电脑寄存器是如何工作的。维基百科上说,pc 寄存器保存下一条要执行的指令的值,但是,查看二进制忍者的反汇编图以查找同一指令块,似乎这并不完全正确。
这是二进制忍者的反汇编图的一部分,其中每个内存加载前面都写入了加载发生的内存地址。

000080ec ldr r3, [pc, #76] -> 0x813c = 0x80f0 + 0x4c -> pc = 80f0 ?? (shouldnt it be 80ee).
000080ee cmp r3, #0
000080f0 it eq
000080f2 ldreq r3, [pc, #68] -> 0x8138 = 0x80f4 + 0x44 -> pc = 80f4 (this makes sense).
000080f4 mov sp, r3
000080f6 sub.w sl, r3, #65536 (edited)
Run Code Online (Sandbox Code Playgroud)
这也发生在代码中,并不总是电脑保存下一条要执行的指令的地址..有什么我应该考虑的吗?
在PC(程序计数器)寄存器发生变化的所有可能性中,我发现了这些:
1) PC increases its value with loading new instruction
2) with jumps and branches
3) with calling subroutine
4) with return from subroutine
Run Code Online (Sandbox Code Playgroud)
这些都是我遗失的东西吗?
我来自这篇文章.