【问题标题】:How do I use mov si, word[ecx] in my x86 assembly code with MASM?如何在我的 x86 汇编代码中使用 mov si, word[ecx] 和 MASM?
【发布时间】:2018-08-29 03:46:08
【问题描述】:

我有一组 x86 汇编代码中的指令,如下所示:

[0x401240]
mov edx, str.HelloWorld
mov eax, ecx
push esi
   |
   |
   v
[0x401248]
mov si, word [eax]
cmp si, word [edx]
jne 0x40126e

ecx 是我在程序运行后传递给程序的字符串。我对装配完全陌生,所以我不完全确定这里发生了什么,但我认为mov si, word [eax] 行是说“从eax 中取两个字节并将si 设置为等于那个。为了测试一下,我想自己写个小脚本,把这个操作的结果打印到控制台。所以参考网上的教程,整理了一下:

.386
.model flat, stdcall
option casemap :none

include \masm32\include\kernel32.inc
include \masm32\include\masm32.inc
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\masm32.lib

.data
    message db "Hello world!", 0

.code

main:
    mov si, word [message]
    invoke StdOut, si
    invoke ExitProcess, 0
end main

不幸的是,通过\masm32\bin\ml /c /Zd /coff test.asm 运行它会导致test.asm(16): error A2009: syntax error in expression。我该如何解决这个问题并检验我的假设?

【问题讨论】:

  • 不,从内存中取出 2 个字节,使用 EAX 作为加载的地址。 [] 使其成为引用内存操作数的寻址模式。对于 MASM,它是 word ptr 而不仅仅是 word。看起来您找到了一个 NASM 语法示例,因为 mov si, word [message] 是有效的 NASM 语法。
  • “为了测试这个” - 使用调试器。在 ASM 中,您很可能会在尝试产生有意义的调试输出时破坏/修改某些内容,而调试器经过验证,并且是如何在每条指令之后检查完整 CPU 状态的强大解决方案。如果你提到 MASM,你可能有 VS,它应该包含调试器。
  • @brittenb 当然,您不能在 linux 下运行 exe 文件,可执行文件是特定于平台的。 (实际上,您可以使用“wine”在 linux 下运行 exe 文件,这是一种 Windows 模拟器,但是 gdb 不仅会调试 exe 的代码,还会调试“wine”的代码,因为这是运行的本机部分linux下)。如果您对特定的 windows exe 感兴趣,那么最好检查一下 Visual Studio 调试器,应该有一些方法可以在其中调试机器代码,真的......或者编写 linux 程序集(NASM 可以用于两者,所以语法将相同,但操作系统服务调用不同)。
  • @brittenb: "take 2 bytes from eax" 将复制 EAX 的低 2 个字节,没有取消引用它。即mov si, ax。听起来这是一个术语问题:您将其视为来自该地址的负载,但您使用的词语会更准确地描述寄存器到寄存器mov(这也是可能的,但在这种情况下通常没有用)。一些 asm 新手实际上确实混淆了指针与指向数据,以及 [] 在 asm 语法中的含义。 (特别是如果他们不熟悉 C 中的指针,我想。)
  • mov si, ax根本不涉及内存。我假设您的意思是 esivalue0x12345678 (这可能是也可能不是存储某些东西的有效地址,我们不在乎,除非我们有指向 64k 对齐缓冲区的指针,我们想用新的偏移量替换低 16 位地址位)。这里没有“指向”。无论如何,esi 中的值将变为0x12345790,替换整个 ESI 寄存器(又名 SI)的最低有效 2 个字节,而保持高字节不变。 x86 partial register usage.

标签: assembly x86 masm masm32


【解决方案1】:

mov si, word [message] 是 NASM 语法。 MASM 中的等价物是

mov si, word ptr [message]

几乎所有 32 位 Windows 的过程都需要 DWORD 作为参数。 SI 是一个单词。改变

invoke StdOut, si

invoke StdOut, esi

MASM32 过程StdOut 需要一个指向空终止字符串的指针。使用MOV 你得到的是值,而不是指针使用LEA 得到指针。改变

mov si, word ptr [message]

lea esi, [message]

您也可以立即加载指针:

mov esi, OFFSET message

您的根本问题的答案是:mov si, word [eax]EAX 指向的字加载到寄存器SI 中,这是ESI 的下部。要测试的脚本应如下所示:

INCLUDE \masm32\include\masm32rt.inc

.data
    message db "Hello world!", 0

.code

main:
    xor esi, esi
    mov eax, OFFSET message
    mov si, WORD PTR [eax]

    printf ("0x%x",esi)

    invoke ExitProcess, 0
end main

【讨论】:

  • 这太好了,谢谢!我需要绕开它,但使用你的代码是可行的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-18
  • 2016-08-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多