Assembly 可以在8086汇编中操作指令指针吗?

Assembly 可以在8086汇编中操作指令指针吗?,assembly,x86-16,Assembly,X86 16,我想知道我是否可以在8086汇编中操作(读取和更改)指令指针(IP)的值 比如说, 假设IP当前正在存储0200h。我想读取此值并将其更改为其他值,例如4020h。我该怎么做呢?如果要将指令指针设置为已知值,例如十六进制值4020h,可以直接跳到该地址: jmp 4020h 或者,如果某个内存位置,myVariable保存了要存储在IP中的值,则可以执行间接跳转: jmp [myVariable] jmp(间接或直接)的结果修改指令指针 读取指令指针有问题。在Linux上定位独立代码,使用一

我想知道我是否可以在8086汇编中操作(读取和更改)指令指针(IP)的值

比如说,


假设IP当前正在存储
0200h
。我想读取此值并将其更改为其他值,例如
4020h
。我该怎么做呢?

如果要将指令指针设置为已知值,例如十六进制值4020h,可以直接跳到该地址:

jmp 4020h
或者,如果某个内存位置,
myVariable
保存了要存储在
IP
中的值,则可以执行间接跳转:

jmp [myVariable]
jmp(间接或直接)的结果修改指令指针

读取指令指针有问题。在Linux上定位独立代码,使用一组类似以下的代码:

 call getIP

有关读取IP的其他方法,请参阅。

相关:(我更新了被接受的答案,使其不那么糟糕,并且涵盖了32位和64位,因为这是阅读IP的标准问答。没有提到写IP,因为这是一种概念上的理解:写IP是一种跳跃,但您的代码可能在不知道加载位置的情况下运行,所以用例完全不同不一样。)

还有一个近乎重复的问题:询问为什么RIP/EIP/IP不直接公开以用于在AX等整数寄存器上工作的指令(即为什么
添加IP,AX
不作为间接跳转)TL:DR:像ARM这样的一些ISA确实将程序计数器公开为一个整数寄存器,但x86只有很少的寄存器,在机器代码中对IP使用一个寄存器编码会去掉一个通用整数寄存器


您可以使用
jmp
call
直接编写
IP
,但只能通过
call
推送来读取

(从技术上讲,
call
不是读取
IP
的唯一选项。您可以使用
int
或其他中断,让中断处理程序在
iret
之前查看上下文,但这与
call
的想法相同,只是更复杂、更慢。)


在位置相关代码中,每个指令的地址在链接时都是已知的。您可以将任何标签的地址用作立即常数或寻址模式的一部分。例如

mov ax, $         ; ax = address of the start of the MOV instruction (NASM syntax)


假设IP当前正在存储
0200h
我想读取此值并将其更改为其他值,例如
4020h
。我该怎么做

拨打4020h

在给定当前IP的情况下,汇编程序将计算出要使用的
rel16
置换量。(或者,如果您希望以位置无关的方式跳转到固定的
IP
值,您可以将
4020h
放入寄存器并
调用ax
)(相对于
cs
的偏移量,因此仍然不是绝对地址。为此,您需要一个
远呼叫
,并且可以使用
ptr16:16
绝对直接,将地址作为立即数。)

旧值(+调用指令的长度)将位于堆栈上,
4020h
处的代码可以用
pop
弹出(或者用
ret
弹出回IP),或者用
mov
加载


一般来说,避免错误匹配
调用
/
返回
(即,不要只
将返回地址弹出
到寄存器中,然后使用
jmp
返回)。这将导致分支预测失误,因为返回地址预测器堆栈不平衡。(和)

在比PIII更新的CPU上,
调用next\u insn
/
pop ax
是有效的,因为。请参阅

@mksteve建议调用执行
mov bx[sp]
/
ret
的函数,而不是只调用
next\u指令
/
pop bx
,这在早期的Intel P6系列CPU(如PPro)上很好。但请注意
[sp]
不是一种有效的16位寻址模式,因此这在16位中显得格外笨重。如果您真的想在16位代码中使用,可能
pop-ax
/
push-ax
/
ret
会让您的工作更轻松



在64位代码中,您可以更直接地读取RIP的当前值:
lea-rax,[RIP]
。这更常用于静态数据的位置独立寻址。例如
lea-rax,[rel-my_-table]
添加dword[rel-global_-counter],2
将告诉汇编器+链接器确定使用什么
rel32
来达到所需的符号。这在可执行文件或动态库中起作用,即使库加载在不同的地址,代码和数据之间的距离也是恒定的。

@Doda这没有问题。调用wheremi:POP AX,JMPAX@Doda阅读9086用户手册了解体系结构,阅读汇编程序手册了解说明。然后您将能够理解mksteve的答案并对其进行表决。ATM,在得到一个好的答案后,您似乎在问一些无关的问题。JMP指令直接更改IP寄存器的值-仅此而已。IP寄存器不会更改oes在内存映射中没有地址。0x1234只是一个用作示例的值。您提出的问题毫无意义。请阅读手册。在询问有关说明详细信息之前,您需要了解体系结构和计算机的工作方式。@Doda-处理否决票的方法是发表新文章并获得否决票。:-)投票被否决的一个可能的解释是,一些人知道
MOV IP,X
并没有丢失,只是拼写了
JMP X
,你也许可以通过阅读英特尔的手册来发现这一点。@Doda你被否决是因为你问了一个问题,这个问题可以用谷歌或通过查看e手册。没有办法摆脱否决票。不要删除问题,但下次请进行一些研究
mov ax, $         ; ax = address of the start of the MOV instruction (NASM syntax)
mov  ax, label   ; or MASM:  mov ax, OFFSET label

label: