首先,使用NASM,目标是x86,并在x86的16位实模式下运行。 我想将一个内存位置的代码复制到另一个内存位置,然后对目标执行调用/ jmp,这样我就可以在那里执行代码了。代码最初位于0x1000:0x0(段:偏移量)。现在,我想复制它,比如说0x3000:0x0。而且代码大小完全是512字节。我正试图通过以下例程来做到这一点。
org 0x500
;The code to be copied is located at 0x1000:0x0. We want to copy it to 0x3000:0x0
copy:
mov esi,0x1000 ; source address of the code in DS:SI
mov edi,0x3000 ; destination address of the code in ES:DI
mov ecx,0x200 ; size of the code, 512 bytes (0x200)
rep movsb ; copy bytes from address in SI to address in DI.
jmp 0x3000:0x0 ; jump to the destination , and execute the code there.
正在复制的代码只打印一个字符串。因此,如果上面的代码段工作,我会在屏幕上看到该字符串。此外,我已经验证复制的代码是有效的,并且确实存在于0x1000:0x0,所以没有出现这样明显/愚蠢的错误。 由于某种原因,上述例程失败了。在我看来,可能的失败点可能是错误的地址。在复制之前,我不确定在SI和DI中放入什么。这些应该是抵消还是实际地址?文档没有说清楚。另外,我应该明确初始化ES和DS吗?
我尝试了各种各样的组合来尝试使这项工作,但无济于事。其中一个就是:
org 0x500
;The code to be copied is located at 0x1000:0x0. We want to copy it to 0x3000:0x0
copy:
mov bx,0x1000
mov ds,bx ; set DS explicitly to 0x1000.
mov esi,0x0 ; source address of the code in DS:SI (0x1000:0x0)
mov bx,0x3000
mov es,bx ; set ES explicitly to 0x3000
mov edi,0x0 ; destination address of the code in ES:DI (0x3000:0x0)
mov ecx,0x200 ; size of the code, 512 bytes (0x200)
rep movsb ; copy bytes from address in SI to address in DI.
jmp 0x3000:0x0 ; jump to the destination , and execute the code there.
所以在这里我明确设置了ES:DI和DS:SI。这也行不通。我也试过给SI和DI提供实际的物理地址,但是失败了。现在,我没有选择。我确信在这里有一些概念性的内存寻址错误,但是我无法理解它。 (是的,复制的代码大小为512字节,原始二进制)。
感谢。
答案 0 :(得分:2)
您确定要复制的代码是位置无关的,还是在地址0x3000而不是0x1000处正确?一些指令(如CALL和长JMP)是绝对的,其他指令(如短JMP)是相对于指令的地址。
答案 1 :(得分:0)
你发布的第二段示例代码应该可以工作,只要方向标志是明确的(如果它可能不是那么做一个“CLD”指令),并且只要你没有丢弃你自己的堆栈或任何东西
如果它不起作用(并且鉴于第一个例子非常混乱),我很想假设你在其他地方犯了一个错误(例如,你可能从磁盘的错误扇区加载了数据)到0x1000:0x0000,你正确地复制了错误的数据或其他东西。)
任何人都可以给你的最佳建议可能是学习如何单步执行代码(并查看注册内容,设置断点,检查内存等),例如Bochs模拟器中内置的调试器。
答案 2 :(得分:-2)
最终以一种奇怪的方式解决了这个问题。好的,该计划的前几行有这个:
org 0x500
mov ax,cs
mov ds,ax
mov es,ax
接下来是复制程序。我编写了代码:(并且有效)
org 0x500
xor ax,ax ;make ax 0, instead of copying CS to it
mov ds,ax
mov es,ax
通过此更改,我发布的第一个复制例程也有效。我不知道为什么。我正在玩这些段值,然后单击。