汇编代码和机器代码有什么区别?如果汇编指令相当于机器指令,那我为什么不理解它们之间的差异呢?

4
有些人说汇编语言等于机器语言,只是我们在汇编语言中使用助记符。
读完彼得索尔德的《编码》后,我仍然无法理解某些汇编代码如何转换成机器码。
例如(来自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

在机器码中?
5个回答

2

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

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


1
语法取决于汇编器,对于MASM或ML(Microsoft的MASM版本),语法将是:
        mov     ecx,offset msg    ;ecx = offset (address) of msg

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

1
你的问题很好,涉及到计算机基本概念中的“间接引用”。
计算机通常处理文本字符串(如“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以查找实际文本消息的开头。这有意义吗?

但是这个汇编代码如何被翻译成机器码呢?section .data msg db 'Hello, world!', 0xa。我的意思是它的“机器码”版本是什么? - Coder88
是的,我看到了你的问题。它的答案很微妙,不容易理解。内存模型需要一些时间来适应。section .data本身并不生成机器代码,而是为您进一步使用配置汇编器。db 'Hello, world!', 0xa只是制作了我上面描述的字节字符串。您没有告诉汇编器在内存中放置这个字符串的位置,因此它选择一个位置,例如在地址0x8201处。然后符号msg表示地址(仅是一个数字)0x8201。这都是符号化的,需要一些思考。祝你好运。 - thb
明白了。因此,并非所有汇编代码中的内容都有直接对应的机器码。 - Coder88

0

对于x86,英特尔的指令参考手册列出了每个指令的所有编码(请参见https://stackoverflow.com/tags/x86/info中的链接)。

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

mov ecx,[msg]将从绝对地址(msg的开头)进行4字节加载。它将使用源的内存操作数编码为mov r32,r/m32

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


0

据我理解,该命令

mov ecx,msg

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

msg db 'Hello, world!', 0xa

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


该汇编代码假定“Hello world”字符串已经在内存中,并且字符串从0xa开始。但是这个汇编代码如何被转换成机器码呢? section .data msg db'Hello,world!',0xa。我的意思是它的“机器码”版本是什么? - Coder88
据我理解,字符串实际上并没有被转换为机器码。汇编器显然会生成一些二进制文件,其中包括已翻译的代码和一些原始数据,这些数据也包含在二进制文件中,并可以在被汇编的文件中定义。 - Codor

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接