汇编程序如何工作?
我正在寻找有关在生成机器代码时使用汇编器的简要描述。
所以我知道汇编是机器代码的 1:1 翻译。但我对目标代码和链接器以及它们如何放入其中感到困惑。
我不需要复杂的答案,一个简单的答案就可以了
I am looking for a brief description of the use of an assembler in producing machine code.
So I know that assembly is a 1:1 translation of machine code. But I am getting confused about object code and linkers and how they place into it.
I don't need a complex answer just a simple one will do fine
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
汇编器和编译器都将源文件翻译成目标文件。
目标文件实际上是最终可执行输出(由链接器生成)之前的中间步骤。
链接器获取指定的目标文件和库(它们是目标文件的包)并解析重定位(或“修复”)记录。
当编译器/汇编器不知道源代码中使用的函数或变量的地址时,会生成这些重定位记录,并按名称生成对其的引用,该引用可以由链接器解析。
例如,假设您希望程序将一条消息打印到屏幕上,分为两个源文件,并且您希望单独组装它们并链接它们(例如使用 Linux x86-64 系统调用) -
main.asm :
message.asm :
如果您组装这些并查看 main.asm 的目标文件输出(例如 objdump -d main.o),您会注意到“call do_message”的地址为 00 00 00 00 - 无效。
但是,为地址的 4 个字节创建了重定位记录:
偏移量为“1”,类型为“R_X86_64_PC32”,告诉链接器解析此引用,并将解析后的地址放入指定的偏移量中。
当您将最终程序与“ld -o program main.o message.o”链接时,所有重定位都已解决,如果没有任何问题未解决,则留下可执行文件。
当我们“objdump -d”可执行文件时,我们可以看到解析的地址:
相同类型的重定位用于变量和函数。
当您将程序链接到多个大型库(例如 libc)时,会发生相同的过程 - 您定义一个名为“main”的函数,libc 有一个外部引用 - 然后 libc 在您的程序之前启动,并在以下情况下调用您的“main”函数您运行可执行文件。
Both an assembler and a compiler translate source files into object files.
Object files are effectively an intermediate step before the final executable output (generated by the linker).
The linker takes the specified object files and libraries (which are packages of object files) and resolves relocation (or 'fixup') records.
These relocation records are made when the compiler/assembler doesn't know the address of a function or variable used in the source code, and generates a reference for it by name, which can be resolved by the linker.
For example, say you want a program to print a message to the screen, seperated into two source files, and you want to assemble them seperately and link them (example using Linux x86-64 syscalls) -
main.asm :
message.asm :
If you assemble these and look at the object file output of main.asm (eg, objdump -d main.o), you will notice the 'call do_message' has an address of 00 00 00 00 - which is invalid.
But, a relocation record is made for the 4 bytes of the address :
The offset is '1' and the type is 'R_X86_64_PC32' which tells the linker to resolve this reference, and put the resolved address into the specified offset.
When you link the final program with 'ld -o program main.o message.o', the relocations are all resolved, and if nothing is unresolved, you are left with an executable.
When we 'objdump -d' the executable, we can see the resolved address :
The same kind of relocations are used for variables as well as functions.
The same process happens when you link your program against multiple large libraries, such as libc - you define a function called 'main' which libc has an external reference to - then libc is started before your program, and calls your 'main' function when you run the executable.
简单解释:
一旦汇编语言被汇编成目标代码,链接器就用于将目标代码转换为计算机可以理解和运行的可执行命令。生成的机器码可以由CPU的控制器解释。
Simple explanation:
Once the assembly language is assembled into object code, the linker is used to convert the object code into an executable of commands that the computer can understand and run. The generated machine code can be interpreted by the cpu's controller.