【问题标题】:MASM routine to read dword from 32 bit addressMASM 例程从 32 位地址读取 dword
【发布时间】:2012-06-01 19:42:48
【问题描述】:

因此,我们的一个项目遇到了一些需要编写的汇编代码的障碍。我们有一个旧的、旧的(用 Borland 1992 编译的)内存测试器 C 程序,它偶尔需要进入汇编程序以从内存的某些区域读取值。我需要编写一个 MASM 汇编例程,它接受一个 32 位内存地址并返回该位置的 dword。我唯一的组装经验是大约 4 年前在 MIPS 的,所以我很生疏。到目前为止,我有这个:

; Do a direct read of a memory address
public _mmap_io
_mmap_io PROC FAR

push  bp          ; 'C' entry    

mov   bp,sp       ; set pointer to parm list
push  es
xor   ax, ax      ; clear ax        
mov   es, ax      ; clear es?
add   bp, 6       ; bump to parms

xor eax,eax       ; clear eax
mov eax, [bp]     ; move the value pointed to by bp into eax
mov esi, eax      ; source index
mov eax,es:[esi]                           

pop   es    
pop   bp          ; 'C' exit    
ret

_mmap_io ENDP

问题是当我读入值时,我得到的东西几乎但不完全是我正在寻找的东西。当我运行类似...

DWORD output = mmap_io(0xEFF87110);
printf("output: %p\n");

output = mmap_io(0xE0000000);
printf("output: %p\n");

在 0xEFF87110 中包含值 0x00000000 且 0xE0000000 中包含 0x80863C00 的内存空间上,我最终得到:

output: 0110:0000
output: 9463:8086

我相信我混淆了我的 16 位和 32 位寄存器,但任何解决这些问题的尝试都导致了进一步的问题。有没有人有更好、更简洁的代码直接从 32 位内存地址读取,或者可以帮助我解决我的问题?

【问题讨论】:

  • 只需使用 32 位寄存器而不是 16 位。 32 位带有“e”前缀。 ESP EBP ESI EDI EAX EBX EDX ECX
  • 该代码已有 20 年历史,适用于 MS-DOS 或 Windows 2.0。事情不再那样工作了!
  • 没有足够的信息来调试这个程序。您编写的汇编代码应该会崩溃,因为它正在运行保护模式并且您已将 NULL 选择器加载到 ES 中,或者因为您正在运行实模式并且0xEFF87110 超过了 16 位实模式段限制。跨度>

标签: assembly masm masm32


【解决方案1】:

这可以在旧的 C 中完成。无需组装。假设“dword”是 32 位:

#include <stdint.h>

uint32_t peek32(uintptr_t address)
{
   volatile uint32_t * ptr = (volatile uint32_t *)address;
   return *ptr;
}

void poke32(uintptr_t address, uint32_t value)
{
   volatile uint32_t * ptr = (volatile uint32_t *)address;
   *ptr = value;
}

16 位和 8 位值可以有类似的版本。

【讨论】:

  • 但是将mmap_io(0xEFF87110) 翻译成peek32(0xEFF87110) 会给你一个很好的访问冲突。要获得内存映射 I/O,您需要一个设备驱动程序。
  • 等一下。提问者说他​​们从 C 中“进入 MASM”以做一些无需离开 C 就可以完成的事情。为什么要投反对票?
  • 只是猜测,投票者不知道任何 32 位系统的代码实际上可以工作。在虚拟内存中运行内存测试器在几个层面上都是不好的。原始代码来自 1992 年,在 16 位 MS-DOS 上运行,您实际上可以访问所有内存。 (请参阅我对这个问题的评论)。
  • 该代码应该是原始代码的替代品。它是否适用于随机的 Windows 框与问题无关。我的假设是它运行的任何进程都有权访问它要测试的内存。有一点你必须停止制造并发症:)
  • uintptr_t 将是更好的地址类型,或者可能只是 uint32_t *。完全同意这可以满足 OP 的要求,无论这是否是一个愚蠢的要求。内存映射 I/O 实际上只是加载和存储。首先需要让操作系统将你的一些虚拟地址空间映射到某个有趣的地方(在具有内存保护的操作系统下,与 DOS 不同),但一旦完成,这就是你要使用的。
猜你喜欢
  • 1970-01-01
  • 2012-02-27
  • 1970-01-01
  • 1970-01-01
  • 2013-04-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-09
相关资源
最近更新 更多