该汇编语言代码是什么意思? [英] What does this assembly language code mean?

查看:226
本文介绍了该汇编语言代码是什么意思?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是一名学生,刚刚开始学习汇编语言.为了更好地理解它,我只是用C编写了一个简短的代码并将其转换为汇编语言.出乎意料的是我一点都不明白.

I am a student and just started studying assembly language. To understand it better I just wrote a short in C and converted it to assembly language. Surprisingly I didn't understand a bit.

代码是:

#include<stdio.h>

int main()
{
    int n;
    n=4;
    printf("%d",n);
    return 0;
}

对应的汇编语言是:

.file   "delta.c"
    .section    .rodata
.LC0:
    .string "%d"
    .text
    .globl  main
    .type   main, @function
main:
.LFB0:
    .cfi_startproc
    pushl   %ebp
    .cfi_def_cfa_offset 8
    .cfi_offset 5, -8
    movl    %esp, %ebp
    .cfi_def_cfa_register 5
    andl    $-16, %esp
    subl    $32, %esp
    movl    $4, 28(%esp)
    movl    $.LC0, %eax
    movl    28(%esp), %edx
    movl    %edx, 4(%esp)
    movl    %eax, (%esp)
    call    printf
    movl    $0, %eax
    leave
    .cfi_restore 5
    .cfi_def_cfa 4, 4
    ret
    .cfi_endproc
.LFE0:
    .size   main, .-main
    .ident  "GCC: (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3"
    .section    .note.GNU-stack,"",@progbits

这些是什么意思?

推荐答案

让我们分解一下:

.file   "delta.c"

编译器正在使用它来告诉您程序集来自的源文件.对于汇编程序来说意义不大.

The compiler is using this to tell you the source file that the assembly came from. It doesn't mean much to the assembler.

.section    .rodata

这将开始一个新的部分. "rodata"是只读数据"部分的名称.本节最后将数据写入可执行文件,该可执行文件将内存映射为只读数据.可执行映像的所有".rodata"页面最终都将由以下所有进程共享: 加载图像.

This starts a new section. "rodata" is the name for the "read-only data" section. This section ends up writing data to the executable that gets memory mapped in as read-only data. All the ".rodata" pages of an executable image end up being shared by all the processes that load the image.

通常,源代码中任何无法优化为汇编内在函数的编译时常数"最终都将存储在只读数据段"中.

Generally any "compile-time-constants" in your source code that can't be optimized away into assembly intrinsics will end up being stored in the "read only data section".

.LC0:
    .string "%d"

.LC0"部分是标签.它提供了一个符号名称,该符号名称引用了文件中紧随其后的再见字词.在这种情况下,"LC0"表示字符串%d". GNU汇编器使用以下约定:以"L"开头的标签被视为本地标签".这具有技术上的意义,这对编写编译器和链接器的人来说最为有趣.在这种情况下,编译器使用它来引用对特定目标文件专用的符号.在这种情况下,它表示一个字符串常量.

The .LC0" part is a label. It provdes a symbolic name that references the byes that occur after it in the file. In this case "LC0" represents the string "%d". The GNU assembler uses the convention that labels that start with an "L" are considered "local labels". This has a technical meaning that is mostly interesting to people who write compilers and linkers. In this case it's used by the compiler to refer to a symbol that is private to a particular object file. In this case it represents a string constant.

.text

这将开始一个新的部分. 文本"部分是目标文件中存储可执行代码的部分.

This starts a new section. The "text" section is the section in object files that stores executable code.

.globl  main

.global"指令告诉汇编程序将其后的标签添加到所生成的目标文件已导出"的标签列表中.这基本上意味着这是链接器应可见的符号".例如,任何声明(或包括)兼容函数原型的c文件都可以调用"C"中的非静态"函数.这就是为什么您可以#include stdio.h然后调用printf的原因.编译任何非静态C函数时,编译器都会生成程序集,该程序集声明指向该函数开头的全局标签.将此与不应链接的内容(例如字符串文字)进行对比.目标文件中的汇编代码仍然需要一个标签来引用文字数据.这些是本地"符号.

The ".global" directive tells the assembler to add the label that follows it to the list of labels "exported" by the generated object file. This basically means "this is a symbol that should be visible to the linker". For example a "non static" function in "C" can be called by any c file that declares (or includes) a compatible function prototype. This is why you can #include stdio.h and then call printf. When any non-static C-function is compiled, the compiler generates assembly that declares a global label that points at the beginning of the function. Contrast this with things that shouldn't be linked, such as string literals. The assembly code in the object file still needs a label to refer to the literal data. Those are "local" symbols.

.type   main, @function

我不确定GAS(gnu汇编程序)如何处理".type"指令.但是,这会指示汇编程序,标签"main"是指可执行代码,而不是数据.

I don't know for sure how GAS (the gnu assembler) processes ".type" directives. However, this instructs the assembler that the label "main" refers to executable code, as opposed to data.

main:

这定义了主要"功能的入口点.

This defines the entry point for your "main" function.

.LFB0:

这是一个本地标签",指的是功能的开始.

This is a "local label" that refers to the start of the function.

    .cfi_startproc

这是呼叫框架信息"指令.它指示汇编程序发出侏儒格式的调试信息.

This is a "call frame information" directive. It instructs the assembler to emit dwarf format debugging information.

    pushl   %ebp

这是汇编代码中功能序言"的标准部分.它保存"ebp"寄存器的当前值. "ebp"或基本"寄存器用于存储函数中堆栈帧的基本".当在函数中调用函数时,"esp"(堆栈指针")寄存器可以更改,而"ebp"保持不变.始终可以相对于"ebp"访问函数的任何参数.通过ABI调用约定,在功能可以修改EBP寄存器之前,它必须保存它,以便可以在函数返回之前恢复原始值.

This is a standard part of a function "prologue" in assembly code. It's saving the current value of the "ebp" register. The "ebp" or "base" register is used to store the "base" of the stack frame within a function. Whereas the "esp" ("stack pointer") register can change as functions are called within a function, the "ebp" remains fixed. Any arguments to the function can always be accessed relative to "ebp". By ABI calling conventions, before a functon can modify the EBP register it must save it, so that the original value can be restored before the function returns.

    .cfi_def_cfa_offset 8
    .cfi_offset 5, -8

我没有详细研究这些内容,但我相信它们与DWARF调试信息有关.

I haven't investigated these in detail, but I believe they are related to DWARF debugging information.

    movl    %esp, %ebp

GAS使用AT& T语法,该语法与Intel手册使用的语法相反.这意味着将ebp设置为等于esp".基本上,这将为该函数的其余部分建立基本指针".

GAS uses AT&T syntax, which is backwards from what the Intel manual uses. This means "set ebp equal to esp". This basically establishes the "base pointer" for the rest of the function.

    .cfi_def_cfa_register 5
    andl    $-16, %esp
    subl    $32, %esp

这也是该功能的一部分.这将对齐堆栈指针,然后从堆栈指针中减去足够的空间以容纳该函数的所有局部变量.

This is also part of the epilouge for the function. This aligns the stack pointer, and then subtracts enough room from it to hold all the locals for the function.

    movl    $4, 28(%esp)

这会将32位整数常量4加载到堆栈帧中的插槽中.

This loads the 32 bit integer constant 4 into a slot in the stack frame.

    movl    $.LC0, %eax

这会将上面定义的%d"字符串常量加载到eax中.

This loads the "%d" string constant defined above into eax.

    movl    28(%esp), %edx

这会将存储在堆栈中的偏移量28中的值"4"加载到edx.很有可能您的代码是在关闭优化的情况下编译的.

This loads the value "4" stored in offset 28 in the stack to edx. Chances are your code was compiled with optimizations turned off.

    movl    %edx, 4(%esp)

然后将值4移动到堆栈上,即调用printf时所需的位置.

This then moves the value 4 onto the stack, in the place it needs to be when calling printf.

    movl    %eax, (%esp)

这会将字符串%d"加载到调用printf时所需的堆栈位置.

This loads the string "%d" into the place on the stack it needs to be when calling printf.

    call    printf

这称为printf.

    movl    $0, %eax

这会将eax设置为0.由于下一条指令是"leave"和"ret",因此这等效于C代码中的"return 0". EAX寄存器用于保存函数的返回值.

This sets eax to 0. Given that the next instructions are "leave" and "ret", this is equavlent to "return 0" in C code. The EAX register is used to hold your function's return value.

    leave

此指令清除呼叫帧.它将ESP设置回EBP,然后将EBP弹出修改后的堆栈指针.像下一条指令一样,这也是该函数的结尾部分.

This instruction cleans up the call frame. It sets ESP back to EBP, then pops EBP out of the modified stack pointer. Like the next instruction this is part of the function's epilogue.

    .cfi_restore 5
    .cfi_def_cfa 4, 4

这是更多DWARF的东西

This is more DWARF stuff

    ret

这是实际的返回指令.它从函子返回

This is the actual return instruction. It returns from the functon

    .cfi_endproc
.LFE0:
    .size   main, .-main
    .ident  "GCC: (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3"
    .section    .note.GNU-stack,"",@progbits

这篇关于该汇编语言代码是什么意思?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆