【发布时间】: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根本不涉及内存。我假设您的意思是esi的 value 是0x12345678(这可能是也可能不是存储某些东西的有效地址,我们不在乎,除非我们有指向 64k 对齐缓冲区的指针,我们想用新的偏移量替换低 16 位地址位)。这里没有“指向”。无论如何,esi中的值将变为0x12345790,替换整个 ESI 寄存器(又名 SI)的最低有效 2 个字节,而保持高字节不变。 x86 partial register usage.