如果汇编代码指令等同于机器代码指令,我不明白这些汇编代码和机器代码的区别

I don't understand these assembly code and machine code differences if assembly code instructions are equivalent of machine code instructions

有人说汇编语言=机器语言,只是我们在汇编语言中使用助记符。

读了 Petzold 的 "CODE",我仍然无法理解一些汇编代码是如何翻译成机器代码的。

例如(来自 Tutorials Point 的组装课程):

_start:             ;tells linker entry point
   mov  edx,len     ;message length
   mov  ecx,msg     ;message to write

section .data
msg db 'Hello, world!', 0xa  ;our dear string

据我了解,msg 包含 "Hello, world!" 并且已移入 ECX。

但据我所知,在 x86 中,ECX 只能存储 32 位。

那么我们如何将超过 32 位的 "Hello, world!" 移动到 ECX 中?

那部分的等价物是什么

section .data
msg db 'Hello, world!', 0xa  ;our dear string

在机器码中?

据我了解,命令

mov ecx,msg

实际上并没有将整个字符串 Hello, world! 移动到寄存器,而是指向其开头的指针。汇编指令

msg db 'Hello, world!', 0xa

显然定义了一个内存位置,其中包含实际的字符串 Hello, world! 并且可以由标签 msg 引用。但是,实际使用情况有点难说,因为缺少对寄存器内容的进一步使用。

使用 msg db 定义包含字节字符串序列的地址。使用 mov ecx, msg 你只加载这个地址而不是它的内容。然后可以通过加载 [ecx]、[ecx+1] 等来加载字符串

.data 定义程序部分。 .text 通常包含机器代码,.data 可修改的程序代码。可以有更多,例如异常处理标签等

你的问题很好。它涉及 间接的基本计算机概念。

计算机处理像 "Hello, world!" 这样的文本字符串的正常方法是将其作为一系列字符保存在内存中。例如:

Memory address    Memory contents
8201              'H'
8202              'e'
8203              'l'
8204              'l'
8205              'o'
8206              ','
8207              ' '
...               ...
820E              0

本例中msg的值为0x8201。它不是'H'。因此,值 0x8201 被移动到寄存器 ecx.

稍后,任何想要该消息的人都可以从ecx中读取0x8201,然后转到内存地址0x8201找到实际文本消息的开头。这有意义吗?

语法取决于汇编程序,对于 MASM 或 ML(Microsoft 版本的 MASM),语法为

        mov     ecx,offset msg    ;ecx = offset (address) of msg

这清楚地表明 msg 的偏移量或地址正在加载到 ecx 中,而不是 msg 的前 4 个字节。

对于 x86,Intel 的 insn 参考手册列出了每条指令的所有编码(参见 https://whosebug.com/tags/x86/info 中的 link)。

mov ecx, msgmov r32, imm32 编码。 msg的地址最终在link时被填入指令中的那4个字节,因为那是确定最终绝对地址的时间。

mov ecx, [msg] 将从绝对地址(msg 的开头)加载 4 字节。它将被编码为 mov r32, r/m32,对源使用 memory-operand 编码。

len 可能是用 equ 汇编指令定义的。所以它是一个 符号 ,但它的值不是地址。相反,它的值是 asm 源文件中的一个数字。 msg是一个符号,也是一个标签,其值一个地址。